@oj-module/cli 0.2.47 → 0.2.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/devkit/SKILL.md +1 -1
- package/devkit/framework-dev.md +2 -2
- package/devkit/manual.md +24 -14
- package/devkit/module-dev-and-cdn-playground.md +2 -2
- package/devkit/wecom-daikaifa.md +237 -14
- package/package.json +2 -2
- package/shell-dist/assets/runtime.js +2 -2
- package/shell-dist/index.html +2 -2
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/templates-tenant-scope.test.ts +7 -2
- package/src/init.ts +1 -1
- package/src/market/__tests__/bootstrap.test.ts +1 -1
- package/src/market/__tests__/setup.test.ts +7 -7
- package/src/market/bootstrap.ts +1 -1
- package/templates/README.md +1 -1
- package/templates/init.include.yaml +12 -0
- package/templates/openapi.json +2863 -549
- package/templates/src/_platform/api/_shared/service/domain/contacts.ts +7 -0
- package/templates/src/_platform/api/_shared/service/domain/org-read.ts +451 -0
- package/templates/src/_platform/api/_shared/service/domain/org.ts +566 -0
- package/templates/src/_platform/api/_shared/service/domain/users.ts +140 -2
- package/templates/src/_platform/api/_shared/service/infra/query.ts +2 -1
- package/templates/src/_platform/api/fixtures/l1-test-user.sql +1 -1
- package/templates/src/_platform/api/manifest.yaml +3 -0
- package/templates/src/_platform/api/migrations/0016__org.mysql.sql +41 -0
- package/templates/src/_platform/api/migrations/0016__org.pg.sql +40 -0
- package/templates/src/_platform/api/migrations/0016__org.sql +62 -0
- package/templates/src/_platform/api/org/departments/api.ts +51 -0
- package/templates/src/_platform/api/org/is-member/api.ts +33 -0
- package/templates/src/_platform/api/org/members/api.ts +55 -0
- package/templates/src/_platform/api/org/picker/api.ts +59 -0
- package/templates/src/_platform/api/org/resolve/api.ts +38 -0
- package/templates/src/_platform/api/org/tree/api.ts +37 -0
- package/templates/src/_platform/api/org/user/api.ts +46 -0
- package/templates/src/_platform/api/schema.yaml +48 -0
- package/templates/src/_platform/api/seed.mysql.sql +10 -5
- package/templates/src/_platform/api/seed.pg.sql +10 -5
- package/templates/src/_platform/api/seed.sql +13 -5
- package/templates/src/_platform/web/__client/api.schemas.ts +126 -0
- package/templates/src/_platform/web/__client/api.ts +170 -1
- package/templates/src/auth/api/_shared/ldap-login.ts +2 -0
- package/templates/src/auth/api/_shared/session.ts +5 -1
- package/templates/src/auth/api/_shared/wecom/admin.ts +3 -1
- package/templates/src/auth/api/_shared/wecom/client.ts +243 -31
- package/templates/src/auth/api/_shared/wecom/config.ts +12 -1
- package/templates/src/auth/api/_shared/wecom/contacts.ts +263 -0
- package/templates/src/auth/api/_shared/wecom/crypt.ts +17 -7
- package/templates/src/auth/api/_shared/wecom/events.ts +111 -26
- package/templates/src/auth/api/_shared/wecom/login.ts +152 -1
- package/templates/src/auth/api/_shared/wecom/payload.ts +116 -0
- package/templates/src/auth/api/_shared/wecom/store.ts +65 -0
- package/templates/src/auth/api/_shared/wecom/sync.ts +487 -0
- package/templates/src/auth/api/manifest.yaml +3 -0
- package/templates/src/auth/api/migrations/0002__org_sync.mysql.sql +28 -0
- package/templates/src/auth/api/migrations/0002__org_sync.pg.sql +27 -0
- package/templates/src/auth/api/migrations/0002__org_sync.sql +41 -0
- package/templates/src/auth/api/schema.yaml +31 -0
- package/templates/src/auth/api/wecom/admin/api.ts +3 -1
- package/templates/src/auth/api/wecom/api.ts +100 -18
- package/templates/src/auth/api/wecom/sync/api.ts +199 -0
- package/templates/src/auth/web/__client/api.schemas.ts +97 -0
- package/templates/src/auth/web/__client/api.ts +73 -1
- package/templates/src/notification/api/seed.sql +1 -1
- package/templates/src/system/api/departments/api.ts +142 -0
- package/templates/src/system/api/departments/detach/api.ts +34 -0
- package/templates/src/system/api/departments/members/api.ts +142 -0
- package/templates/src/system/api/departments/move/api.ts +39 -0
- package/templates/src/system/api/users/api.ts +45 -5
- package/templates/src/system/api/users/profile/api.ts +44 -0
- package/templates/src/system/web/__client/api.schemas.ts +143 -0
- package/templates/src/system/web/__client/api.ts +293 -1
- package/templates/src/system/web/entry.ts +6 -0
- package/templates/src/system/web/locales/en-US.json +112 -6
- package/templates/src/system/web/locales/zh-CN.json +112 -6
- package/templates/src/system/web/pages/departments/index.tsx +346 -0
- package/templates/src/system/web/pages/departments/sync-bar.tsx +257 -0
- package/templates/src/system/web/pages/departments/tree.ts +66 -0
- package/templates/src/system/web/pages/errors.ts +1 -1
- package/templates/src/system/web/pages/users/index.tsx +49 -7
- package/templates/src/system/web/pages/wecom/index.tsx +14 -0
- package/templates/tests/l1-builder.test.ts +1 -1
- package/templates/tests/org-departments.spec.ts +311 -0
- package/templates/tests/org-read.spec.ts +469 -0
- package/templates/tests/rbac-contacts.spec.ts +13 -3
- package/templates/tests/rbac-seed.spec.ts +11 -0
- package/templates/tests/seed-role-accounts.spec.ts +6 -2
- package/templates/tests/wecom-admin.spec.ts +1 -0
- package/templates/tests/wecom-connector.spec.ts +115 -8
- package/templates/tests/wecom-crypt.spec.ts +12 -3
- package/templates/tests/wecom-endpoints.spec.ts +182 -14
- package/templates/tests/wecom-org-sync.spec.ts +598 -0
- package/templates/tests/wecom-sync.spec.ts +286 -0
- package/vendor/host-versions.json +3 -3
- package/templates/src/auth/api/_shared/wecom/xml.ts +0 -36
|
@@ -33,7 +33,7 @@ export function createSystemClient(ctx: ModuleContext) {
|
|
|
33
33
|
}
|
|
34
34
|
ctx.register.apiPrefix(API_PREFIX);
|
|
35
35
|
bindRequest(ctx.utils.request);
|
|
36
|
-
return { systemLoginMethodsGet, systemOplogGet, systemOplogPost, systemPermissionsGet, systemRolesGet, systemRolesPost, systemRolesDelete, systemRolesBindingsPut, systemSettingsGet, systemSettingsPut, systemUsersGet, systemUsersPost, systemUsersForbiddenPut, systemUsersPasswordPut, systemUsersRolesPut };
|
|
36
|
+
return { systemDepartmentsGet, systemDepartmentsPost, systemDepartmentsPut, systemDepartmentsDelete, systemDepartmentsMovePut, systemDepartmentsDetachPost, systemDepartmentsMembersGet, systemDepartmentsMembersPost, systemDepartmentsMembersPut, systemDepartmentsMembersDelete, systemLoginMethodsGet, systemOplogGet, systemOplogPost, systemPermissionsGet, systemRolesGet, systemRolesPost, systemRolesDelete, systemRolesBindingsPut, systemSettingsGet, systemSettingsPut, systemUsersGet, systemUsersPost, systemUsersDelete, systemUsersProfilePut, systemUsersForbiddenPut, systemUsersPasswordPut, systemUsersRolesPut };
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -64,6 +64,249 @@ async function toApiError(e: unknown): Promise<unknown> {
|
|
|
64
64
|
return e;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
export type SystemDepartmentsGetData = z.infer<(typeof schemas)["systemDepartmentsGet"]["data"]>;
|
|
68
|
+
|
|
69
|
+
export async function systemDepartmentsGet(): Promise<SystemDepartmentsGetData> {
|
|
70
|
+
const client = ensureReq();
|
|
71
|
+
try {
|
|
72
|
+
const env = await client.get(`system/departments`).json<OjEnvelope<SystemDepartmentsGetData>>();
|
|
73
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
74
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
75
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
76
|
+
const data = env.data as SystemDepartmentsGetData;
|
|
77
|
+
if (import.meta.env.DEV) {
|
|
78
|
+
const { schemas } = await import("./api.schemas");
|
|
79
|
+
const r = schemas["systemDepartmentsGet"].data.safeParse(data);
|
|
80
|
+
if (!r.success)
|
|
81
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
82
|
+
}
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
throw await toApiError(e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type SystemDepartmentsPostBody = z.input<(typeof schemas)["systemDepartmentsPost"]["body"]>;
|
|
91
|
+
export type SystemDepartmentsPostData = z.infer<(typeof schemas)["systemDepartmentsPost"]["data"]>;
|
|
92
|
+
|
|
93
|
+
export async function systemDepartmentsPost(body: SystemDepartmentsPostBody): Promise<SystemDepartmentsPostData> {
|
|
94
|
+
const client = ensureReq();
|
|
95
|
+
try {
|
|
96
|
+
const env = await client.post(`system/departments`, { json: body }).json<OjEnvelope<SystemDepartmentsPostData>>();
|
|
97
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
98
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
99
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
100
|
+
const data = env.data as SystemDepartmentsPostData;
|
|
101
|
+
if (import.meta.env.DEV) {
|
|
102
|
+
const { schemas } = await import("./api.schemas");
|
|
103
|
+
const r = schemas["systemDepartmentsPost"].data.safeParse(data);
|
|
104
|
+
if (!r.success)
|
|
105
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
106
|
+
}
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
throw await toApiError(e);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type SystemDepartmentsPutQuery = z.input<(typeof schemas)["systemDepartmentsPut"]["query"]>;
|
|
115
|
+
export type SystemDepartmentsPutBody = z.input<(typeof schemas)["systemDepartmentsPut"]["body"]>;
|
|
116
|
+
export type SystemDepartmentsPutData = z.infer<(typeof schemas)["systemDepartmentsPut"]["data"]>;
|
|
117
|
+
|
|
118
|
+
export async function systemDepartmentsPut(input: { query: SystemDepartmentsPutQuery, body: SystemDepartmentsPutBody }): Promise<SystemDepartmentsPutData> {
|
|
119
|
+
const client = ensureReq();
|
|
120
|
+
try {
|
|
121
|
+
const env = await client.put(`system/departments`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<SystemDepartmentsPutData>>();
|
|
122
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
123
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
124
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
125
|
+
const data = env.data as SystemDepartmentsPutData;
|
|
126
|
+
if (import.meta.env.DEV) {
|
|
127
|
+
const { schemas } = await import("./api.schemas");
|
|
128
|
+
const r = schemas["systemDepartmentsPut"].data.safeParse(data);
|
|
129
|
+
if (!r.success)
|
|
130
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsPut 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
131
|
+
}
|
|
132
|
+
return data;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
throw await toApiError(e);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type SystemDepartmentsDeleteQuery = z.input<(typeof schemas)["systemDepartmentsDelete"]["query"]>;
|
|
140
|
+
export type SystemDepartmentsDeleteData = z.infer<(typeof schemas)["systemDepartmentsDelete"]["data"]>;
|
|
141
|
+
|
|
142
|
+
export async function systemDepartmentsDelete(query: SystemDepartmentsDeleteQuery): Promise<SystemDepartmentsDeleteData> {
|
|
143
|
+
const client = ensureReq();
|
|
144
|
+
try {
|
|
145
|
+
const env = await client.delete(`system/departments`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemDepartmentsDeleteData>>();
|
|
146
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
147
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
148
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
149
|
+
const data = env.data as SystemDepartmentsDeleteData;
|
|
150
|
+
if (import.meta.env.DEV) {
|
|
151
|
+
const { schemas } = await import("./api.schemas");
|
|
152
|
+
const r = schemas["systemDepartmentsDelete"].data.safeParse(data);
|
|
153
|
+
if (!r.success)
|
|
154
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsDelete 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
155
|
+
}
|
|
156
|
+
return data;
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
throw await toApiError(e);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type SystemDepartmentsMovePutQuery = z.input<(typeof schemas)["systemDepartmentsMovePut"]["query"]>;
|
|
164
|
+
export type SystemDepartmentsMovePutBody = z.input<(typeof schemas)["systemDepartmentsMovePut"]["body"]>;
|
|
165
|
+
export type SystemDepartmentsMovePutData = z.infer<(typeof schemas)["systemDepartmentsMovePut"]["data"]>;
|
|
166
|
+
|
|
167
|
+
export async function systemDepartmentsMovePut(input: { query: SystemDepartmentsMovePutQuery, body: SystemDepartmentsMovePutBody }): Promise<SystemDepartmentsMovePutData> {
|
|
168
|
+
const client = ensureReq();
|
|
169
|
+
try {
|
|
170
|
+
const env = await client.put(`system/departments/move`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<SystemDepartmentsMovePutData>>();
|
|
171
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
172
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
173
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
174
|
+
const data = env.data as SystemDepartmentsMovePutData;
|
|
175
|
+
if (import.meta.env.DEV) {
|
|
176
|
+
const { schemas } = await import("./api.schemas");
|
|
177
|
+
const r = schemas["systemDepartmentsMovePut"].data.safeParse(data);
|
|
178
|
+
if (!r.success)
|
|
179
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsMovePut 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
180
|
+
}
|
|
181
|
+
return data;
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
throw await toApiError(e);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export type SystemDepartmentsDetachPostQuery = z.input<(typeof schemas)["systemDepartmentsDetachPost"]["query"]>;
|
|
189
|
+
export type SystemDepartmentsDetachPostData = z.infer<(typeof schemas)["systemDepartmentsDetachPost"]["data"]>;
|
|
190
|
+
|
|
191
|
+
export async function systemDepartmentsDetachPost(query: SystemDepartmentsDetachPostQuery): Promise<SystemDepartmentsDetachPostData> {
|
|
192
|
+
const client = ensureReq();
|
|
193
|
+
try {
|
|
194
|
+
const env = await client.post(`system/departments/detach`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemDepartmentsDetachPostData>>();
|
|
195
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
196
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
197
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
198
|
+
const data = env.data as SystemDepartmentsDetachPostData;
|
|
199
|
+
if (import.meta.env.DEV) {
|
|
200
|
+
const { schemas } = await import("./api.schemas");
|
|
201
|
+
const r = schemas["systemDepartmentsDetachPost"].data.safeParse(data);
|
|
202
|
+
if (!r.success)
|
|
203
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsDetachPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
204
|
+
}
|
|
205
|
+
return data;
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
throw await toApiError(e);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type SystemDepartmentsMembersGetQuery = z.input<(typeof schemas)["systemDepartmentsMembersGet"]["query"]>;
|
|
213
|
+
export type SystemDepartmentsMembersGetData = z.infer<(typeof schemas)["systemDepartmentsMembersGet"]["data"]>;
|
|
214
|
+
|
|
215
|
+
export async function systemDepartmentsMembersGet(query: SystemDepartmentsMembersGetQuery): Promise<SystemDepartmentsMembersGetData> {
|
|
216
|
+
const client = ensureReq();
|
|
217
|
+
try {
|
|
218
|
+
const env = await client.get(`system/departments/members`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemDepartmentsMembersGetData>>();
|
|
219
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
220
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
221
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
222
|
+
const data = env.data as SystemDepartmentsMembersGetData;
|
|
223
|
+
if (import.meta.env.DEV) {
|
|
224
|
+
const { schemas } = await import("./api.schemas");
|
|
225
|
+
const r = schemas["systemDepartmentsMembersGet"].data.safeParse(data);
|
|
226
|
+
if (!r.success)
|
|
227
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsMembersGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
228
|
+
}
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
throw await toApiError(e);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export type SystemDepartmentsMembersPostQuery = z.input<(typeof schemas)["systemDepartmentsMembersPost"]["query"]>;
|
|
237
|
+
export type SystemDepartmentsMembersPostBody = z.input<(typeof schemas)["systemDepartmentsMembersPost"]["body"]>;
|
|
238
|
+
export type SystemDepartmentsMembersPostData = z.infer<(typeof schemas)["systemDepartmentsMembersPost"]["data"]>;
|
|
239
|
+
|
|
240
|
+
export async function systemDepartmentsMembersPost(input: { query: SystemDepartmentsMembersPostQuery, body: SystemDepartmentsMembersPostBody }): Promise<SystemDepartmentsMembersPostData> {
|
|
241
|
+
const client = ensureReq();
|
|
242
|
+
try {
|
|
243
|
+
const env = await client.post(`system/departments/members`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<SystemDepartmentsMembersPostData>>();
|
|
244
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
245
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
246
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
247
|
+
const data = env.data as SystemDepartmentsMembersPostData;
|
|
248
|
+
if (import.meta.env.DEV) {
|
|
249
|
+
const { schemas } = await import("./api.schemas");
|
|
250
|
+
const r = schemas["systemDepartmentsMembersPost"].data.safeParse(data);
|
|
251
|
+
if (!r.success)
|
|
252
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsMembersPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
253
|
+
}
|
|
254
|
+
return data;
|
|
255
|
+
}
|
|
256
|
+
catch (e) {
|
|
257
|
+
throw await toApiError(e);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export type SystemDepartmentsMembersPutQuery = z.input<(typeof schemas)["systemDepartmentsMembersPut"]["query"]>;
|
|
262
|
+
export type SystemDepartmentsMembersPutBody = z.input<(typeof schemas)["systemDepartmentsMembersPut"]["body"]>;
|
|
263
|
+
export type SystemDepartmentsMembersPutData = z.infer<(typeof schemas)["systemDepartmentsMembersPut"]["data"]>;
|
|
264
|
+
|
|
265
|
+
export async function systemDepartmentsMembersPut(input: { query: SystemDepartmentsMembersPutQuery, body: SystemDepartmentsMembersPutBody }): Promise<SystemDepartmentsMembersPutData> {
|
|
266
|
+
const client = ensureReq();
|
|
267
|
+
try {
|
|
268
|
+
const env = await client.put(`system/departments/members`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<SystemDepartmentsMembersPutData>>();
|
|
269
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
270
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
271
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
272
|
+
const data = env.data as SystemDepartmentsMembersPutData;
|
|
273
|
+
if (import.meta.env.DEV) {
|
|
274
|
+
const { schemas } = await import("./api.schemas");
|
|
275
|
+
const r = schemas["systemDepartmentsMembersPut"].data.safeParse(data);
|
|
276
|
+
if (!r.success)
|
|
277
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsMembersPut 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
278
|
+
}
|
|
279
|
+
return data;
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
throw await toApiError(e);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type SystemDepartmentsMembersDeleteQuery = z.input<(typeof schemas)["systemDepartmentsMembersDelete"]["query"]>;
|
|
287
|
+
export type SystemDepartmentsMembersDeleteData = z.infer<(typeof schemas)["systemDepartmentsMembersDelete"]["data"]>;
|
|
288
|
+
|
|
289
|
+
export async function systemDepartmentsMembersDelete(query: SystemDepartmentsMembersDeleteQuery): Promise<SystemDepartmentsMembersDeleteData> {
|
|
290
|
+
const client = ensureReq();
|
|
291
|
+
try {
|
|
292
|
+
const env = await client.delete(`system/departments/members`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemDepartmentsMembersDeleteData>>();
|
|
293
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
294
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
295
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
296
|
+
const data = env.data as SystemDepartmentsMembersDeleteData;
|
|
297
|
+
if (import.meta.env.DEV) {
|
|
298
|
+
const { schemas } = await import("./api.schemas");
|
|
299
|
+
const r = schemas["systemDepartmentsMembersDelete"].data.safeParse(data);
|
|
300
|
+
if (!r.success)
|
|
301
|
+
throw new ContractApiError(-1, `[契约违例] systemDepartmentsMembersDelete 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
302
|
+
}
|
|
303
|
+
return data;
|
|
304
|
+
}
|
|
305
|
+
catch (e) {
|
|
306
|
+
throw await toApiError(e);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
67
310
|
export type SystemLoginMethodsGetData = z.infer<(typeof schemas)["systemLoginMethodsGet"]["data"]>;
|
|
68
311
|
|
|
69
312
|
export async function systemLoginMethodsGet(): Promise<SystemLoginMethodsGetData> {
|
|
@@ -327,6 +570,55 @@ export async function systemUsersPost(body: SystemUsersPostBody): Promise<System
|
|
|
327
570
|
}
|
|
328
571
|
}
|
|
329
572
|
|
|
573
|
+
export type SystemUsersDeleteQuery = z.input<(typeof schemas)["systemUsersDelete"]["query"]>;
|
|
574
|
+
export type SystemUsersDeleteData = z.infer<(typeof schemas)["systemUsersDelete"]["data"]>;
|
|
575
|
+
|
|
576
|
+
export async function systemUsersDelete(query: SystemUsersDeleteQuery): Promise<SystemUsersDeleteData> {
|
|
577
|
+
const client = ensureReq();
|
|
578
|
+
try {
|
|
579
|
+
const env = await client.delete(`system/users`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemUsersDeleteData>>();
|
|
580
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
581
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
582
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
583
|
+
const data = env.data as SystemUsersDeleteData;
|
|
584
|
+
if (import.meta.env.DEV) {
|
|
585
|
+
const { schemas } = await import("./api.schemas");
|
|
586
|
+
const r = schemas["systemUsersDelete"].data.safeParse(data);
|
|
587
|
+
if (!r.success)
|
|
588
|
+
throw new ContractApiError(-1, `[契约违例] systemUsersDelete 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
589
|
+
}
|
|
590
|
+
return data;
|
|
591
|
+
}
|
|
592
|
+
catch (e) {
|
|
593
|
+
throw await toApiError(e);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
export type SystemUsersProfilePutQuery = z.input<(typeof schemas)["systemUsersProfilePut"]["query"]>;
|
|
598
|
+
export type SystemUsersProfilePutBody = z.input<(typeof schemas)["systemUsersProfilePut"]["body"]>;
|
|
599
|
+
export type SystemUsersProfilePutData = z.infer<(typeof schemas)["systemUsersProfilePut"]["data"]>;
|
|
600
|
+
|
|
601
|
+
export async function systemUsersProfilePut(input: { query: SystemUsersProfilePutQuery, body: SystemUsersProfilePutBody }): Promise<SystemUsersProfilePutData> {
|
|
602
|
+
const client = ensureReq();
|
|
603
|
+
try {
|
|
604
|
+
const env = await client.put(`system/users/profile`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<SystemUsersProfilePutData>>();
|
|
605
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
606
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
607
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
608
|
+
const data = env.data as SystemUsersProfilePutData;
|
|
609
|
+
if (import.meta.env.DEV) {
|
|
610
|
+
const { schemas } = await import("./api.schemas");
|
|
611
|
+
const r = schemas["systemUsersProfilePut"].data.safeParse(data);
|
|
612
|
+
if (!r.success)
|
|
613
|
+
throw new ContractApiError(-1, `[契约违例] systemUsersProfilePut 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
614
|
+
}
|
|
615
|
+
return data;
|
|
616
|
+
}
|
|
617
|
+
catch (e) {
|
|
618
|
+
throw await toApiError(e);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
330
622
|
export type SystemUsersForbiddenPutQuery = z.input<(typeof schemas)["systemUsersForbiddenPut"]["query"]>;
|
|
331
623
|
export type SystemUsersForbiddenPutBody = z.input<(typeof schemas)["systemUsersForbiddenPut"]["body"]>;
|
|
332
624
|
|
|
@@ -9,6 +9,7 @@ import { createSystemClient } from "./__client/api";
|
|
|
9
9
|
|
|
10
10
|
const Users = lazy(() => import("./pages/users"));
|
|
11
11
|
const UserRoles = lazy(() => import("./pages/users/roles"));
|
|
12
|
+
const Departments = lazy(() => import("./pages/departments"));
|
|
12
13
|
const Roles = lazy(() => import("./pages/roles"));
|
|
13
14
|
const Oplog = lazy(() => import("./pages/oplog"));
|
|
14
15
|
const Settings = lazy(() => import("./pages/settings"));
|
|
@@ -37,6 +38,11 @@ const routes: AppRouteRecordRaw[] = [
|
|
|
37
38
|
Component: UserRoles,
|
|
38
39
|
handle: { title: "system:menu.userRoles", hideInMenu: true },
|
|
39
40
|
},
|
|
41
|
+
{
|
|
42
|
+
path: "/system/departments",
|
|
43
|
+
Component: Departments,
|
|
44
|
+
handle: { title: "system:menu.departments" },
|
|
45
|
+
},
|
|
40
46
|
{
|
|
41
47
|
path: "/system/roles",
|
|
42
48
|
Component: Roles,
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
"oplog": "Audit Log",
|
|
8
8
|
"settings": "Site Settings",
|
|
9
9
|
"loginMethods": "Login Methods",
|
|
10
|
-
"wecom": "WeCom Integration"
|
|
10
|
+
"wecom": "WeCom Integration",
|
|
11
|
+
"departments": "Departments"
|
|
11
12
|
},
|
|
12
13
|
"common": {
|
|
13
14
|
"confirm": "Confirm",
|
|
@@ -16,7 +17,9 @@
|
|
|
16
17
|
"saved": "Saved",
|
|
17
18
|
"search": "Search",
|
|
18
19
|
"reset": "Reset",
|
|
19
|
-
"create": "Create"
|
|
20
|
+
"create": "Create",
|
|
21
|
+
"edit": "Edit",
|
|
22
|
+
"delete": "Delete"
|
|
20
23
|
},
|
|
21
24
|
"users": {
|
|
22
25
|
"create": "Create User",
|
|
@@ -32,8 +35,12 @@
|
|
|
32
35
|
"email": "Email",
|
|
33
36
|
"roles": "Roles",
|
|
34
37
|
"status": "Account status (forbidden / password change)",
|
|
35
|
-
"actions": "Actions"
|
|
36
|
-
|
|
38
|
+
"actions": "Actions",
|
|
39
|
+
"position": "Position",
|
|
40
|
+
"departments": "Departments"
|
|
41
|
+
},
|
|
42
|
+
"mainDept": "Main dept",
|
|
43
|
+
"filterDept": "Filter by department (incl. sub-depts)"
|
|
37
44
|
},
|
|
38
45
|
"userRoles": {
|
|
39
46
|
"title": "Membership",
|
|
@@ -50,6 +57,46 @@
|
|
|
50
57
|
"titleKey": "Title Key",
|
|
51
58
|
"readonlyHint": "Read-only view: roles and bindings are managed by solution tooling (upsertSolutionPerms)"
|
|
52
59
|
},
|
|
60
|
+
"departments": {
|
|
61
|
+
"create": "New Department",
|
|
62
|
+
"edit": "Edit Department",
|
|
63
|
+
"view": "View",
|
|
64
|
+
"createHint": "Org structure is shared baseline data; WeCom/LDAP are only adapters writing into it",
|
|
65
|
+
"members": "Members",
|
|
66
|
+
"memberCount": "Members",
|
|
67
|
+
"detach": "Manage locally",
|
|
68
|
+
"detachHint": "Once detached, sync no longer rewrites this department — rename/move/delete all open up",
|
|
69
|
+
"readonlyHint": "This department is maintained by an external source; structural fields are read-only",
|
|
70
|
+
"unnamed": "(unnamed)",
|
|
71
|
+
"hidden": "Out of visible scope",
|
|
72
|
+
"removed": "Deleted at source",
|
|
73
|
+
"root": "(top level)",
|
|
74
|
+
"selectUser": "Select user",
|
|
75
|
+
"addMember": "Add member",
|
|
76
|
+
"removeMember": "Remove",
|
|
77
|
+
"noMembers": "No members",
|
|
78
|
+
"confirmDelete": "Delete this department? Its member links are removed too",
|
|
79
|
+
"confirmRemoveMember": "Remove this user from the department?",
|
|
80
|
+
"yes": "Yes",
|
|
81
|
+
"no": "No",
|
|
82
|
+
"origin": {
|
|
83
|
+
"local": "Local",
|
|
84
|
+
"wecom": "WeCom",
|
|
85
|
+
"ldap": "LDAP",
|
|
86
|
+
"sso": "SSO"
|
|
87
|
+
},
|
|
88
|
+
"columns": {
|
|
89
|
+
"name": "Name",
|
|
90
|
+
"nameEn": "English name",
|
|
91
|
+
"parent": "Parent"
|
|
92
|
+
},
|
|
93
|
+
"memberColumns": {
|
|
94
|
+
"user": "User",
|
|
95
|
+
"main": "Main",
|
|
96
|
+
"leader": "Leader",
|
|
97
|
+
"actions": "Actions"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
53
100
|
"oplog": {
|
|
54
101
|
"filterAction": "Action",
|
|
55
102
|
"filterUsername": "Username (prefix)",
|
|
@@ -93,7 +140,8 @@
|
|
|
93
140
|
"env": "Env",
|
|
94
141
|
"status": "Status",
|
|
95
142
|
"installedAt": "Onboarded at",
|
|
96
|
-
"action": "Actions"
|
|
143
|
+
"action": "Actions",
|
|
144
|
+
"authMode": "Auth mode"
|
|
97
145
|
},
|
|
98
146
|
"statusActive": "Active",
|
|
99
147
|
"statusDisabled": "Disabled",
|
|
@@ -103,7 +151,61 @@
|
|
|
103
151
|
"enable": "Enable",
|
|
104
152
|
"disableConfirm": "Disable this app? Members of this corporation will no longer be able to sign in with it.",
|
|
105
153
|
"enableConfirm": "Enable this app?",
|
|
106
|
-
"empty": "No corporations onboarded yet"
|
|
154
|
+
"empty": "No corporations onboarded yet",
|
|
155
|
+
"authModeAdmin": "Admin-authorized",
|
|
156
|
+
"authModeMember": "Member-authorized",
|
|
157
|
+
"authModeHint": "In member-authorized mode the app has no contacts permission, so this corporation's org structure cannot be synced. The corporation admin must switch it to admin-authorized in the WeCom console and re-authorize.",
|
|
158
|
+
"sync": {
|
|
159
|
+
"updatedAt": "WeCom org structure updated {{time}}",
|
|
160
|
+
"neverSynced": "WeCom org structure has never been synced",
|
|
161
|
+
"auto": "auto sync",
|
|
162
|
+
"syncNow": "Sync now",
|
|
163
|
+
"retry": "Retry",
|
|
164
|
+
"resume": "Resume sync",
|
|
165
|
+
"cancel": "Cancel sync",
|
|
166
|
+
"syncing": "Reading WeCom org structure…",
|
|
167
|
+
"syncingProgress": "Syncing: {{done}}/{{total}} departments processed",
|
|
168
|
+
"done": "Sync finished: {{depts}} departments / {{members}} members",
|
|
169
|
+
"paused": "Sync paused ({{depts}} departments processed). Click \"Resume sync\" to continue.",
|
|
170
|
+
"skipped": "{{count}} departments skipped due to permission (normal for departments outside the visible scope)",
|
|
171
|
+
"cancelled": "Sync cancelled",
|
|
172
|
+
"ago": {
|
|
173
|
+
"justNow": "just now",
|
|
174
|
+
"minutes": "{{count}} minutes ago",
|
|
175
|
+
"hours": "{{count}} hours ago",
|
|
176
|
+
"days": "{{count}} days ago"
|
|
177
|
+
},
|
|
178
|
+
"memberAuth": {
|
|
179
|
+
"title": "This corporation uses member-authorized mode: the app has no contacts permission",
|
|
180
|
+
"hint": "Ask the corporation admin to switch to admin-authorized mode in the WeCom console and re-authorize; then sync becomes available."
|
|
181
|
+
},
|
|
182
|
+
"frozen": {
|
|
183
|
+
"title": "Authorization was revoked or the app is disabled: sync is frozen",
|
|
184
|
+
"hint": "The data below is the snapshot from the last successful sync. Ask the service provider to re-onboard the corporation."
|
|
185
|
+
},
|
|
186
|
+
"err": {
|
|
187
|
+
"permission": {
|
|
188
|
+
"title": "The app lacks contacts permission (error {{code}})",
|
|
189
|
+
"hint": "Corporation admin: WeCom console → App management → this app → Permissions, enable the contacts scopes and submit."
|
|
190
|
+
},
|
|
191
|
+
"rateLimited": {
|
|
192
|
+
"title": "WeCom API rate limited (error {{code}})",
|
|
193
|
+
"hint": "Backoff already applied. Click \"Resume sync\" in a moment."
|
|
194
|
+
},
|
|
195
|
+
"ipWhitelist": {
|
|
196
|
+
"title": "Server egress IP is not whitelisted by WeCom (error {{code}})",
|
|
197
|
+
"hint": "The service provider must add the trusted IP in the WeCom console."
|
|
198
|
+
},
|
|
199
|
+
"network": {
|
|
200
|
+
"title": "Cannot reach WeCom ({{code}})",
|
|
201
|
+
"hint": "Check server network access to WeCom and retry."
|
|
202
|
+
},
|
|
203
|
+
"unknown": {
|
|
204
|
+
"title": "Sync failed (error {{code}})",
|
|
205
|
+
"hint": "Contact the service provider to investigate, then retry."
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
107
209
|
},
|
|
108
210
|
"err": {
|
|
109
211
|
"forbidden": "Forbidden",
|
|
@@ -125,5 +227,9 @@
|
|
|
125
227
|
"ldap_base_dn": "LDAP Base DN",
|
|
126
228
|
"ldap_uid_attr": "LDAP UID Attribute",
|
|
127
229
|
"ldap_email_attr": "LDAP Email Attribute"
|
|
230
|
+
},
|
|
231
|
+
"perm": {
|
|
232
|
+
"platform_org_read_all": "Org directory: read all",
|
|
233
|
+
"auth_wecom_sync": "WeCom org sync"
|
|
128
234
|
}
|
|
129
235
|
}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
"oplog": "操作日志",
|
|
8
8
|
"settings": "站点设置",
|
|
9
9
|
"loginMethods": "登录方式",
|
|
10
|
-
"wecom": "企微集成"
|
|
10
|
+
"wecom": "企微集成",
|
|
11
|
+
"departments": "组织架构"
|
|
11
12
|
},
|
|
12
13
|
"common": {
|
|
13
14
|
"confirm": "确认",
|
|
@@ -16,7 +17,9 @@
|
|
|
16
17
|
"saved": "已保存",
|
|
17
18
|
"search": "查询",
|
|
18
19
|
"reset": "重置",
|
|
19
|
-
"create": "新建"
|
|
20
|
+
"create": "新建",
|
|
21
|
+
"edit": "编辑",
|
|
22
|
+
"delete": "删除"
|
|
20
23
|
},
|
|
21
24
|
"users": {
|
|
22
25
|
"create": "建号",
|
|
@@ -32,8 +35,12 @@
|
|
|
32
35
|
"email": "邮箱",
|
|
33
36
|
"roles": "角色",
|
|
34
37
|
"status": "账号状态(禁用/首登改密)",
|
|
35
|
-
"actions": "操作"
|
|
36
|
-
|
|
38
|
+
"actions": "操作",
|
|
39
|
+
"position": "职务",
|
|
40
|
+
"departments": "所属部门"
|
|
41
|
+
},
|
|
42
|
+
"mainDept": "主部门",
|
|
43
|
+
"filterDept": "按部门筛选(含子部门)"
|
|
37
44
|
},
|
|
38
45
|
"userRoles": {
|
|
39
46
|
"title": "成员资格",
|
|
@@ -50,6 +57,46 @@
|
|
|
50
57
|
"titleKey": "标题键",
|
|
51
58
|
"readonlyHint": "只读视图:角色与绑定由解决方案工具链(upsertSolutionPerms)管理"
|
|
52
59
|
},
|
|
60
|
+
"departments": {
|
|
61
|
+
"create": "新建部门",
|
|
62
|
+
"edit": "编辑部门",
|
|
63
|
+
"view": "查看",
|
|
64
|
+
"createHint": "组织架构是各模块共享的基线数据;企微/LDAP 只是写入它的适配器",
|
|
65
|
+
"members": "成员",
|
|
66
|
+
"memberCount": "成员",
|
|
67
|
+
"detach": "转为本地维护",
|
|
68
|
+
"detachHint": "转为本地维护后,同步不再改写该部门,改名/移动/删除全部开放",
|
|
69
|
+
"readonlyHint": "该部门由外部源同步维护,结构字段只读",
|
|
70
|
+
"unnamed": "(未命名)",
|
|
71
|
+
"hidden": "已失去可见范围",
|
|
72
|
+
"removed": "源侧已删除",
|
|
73
|
+
"root": "(顶层)",
|
|
74
|
+
"selectUser": "选择用户",
|
|
75
|
+
"addMember": "添加成员",
|
|
76
|
+
"removeMember": "移出",
|
|
77
|
+
"noMembers": "暂无成员",
|
|
78
|
+
"confirmDelete": "删除该部门?其下成员关联会一并清除",
|
|
79
|
+
"confirmRemoveMember": "把该用户移出本部门?",
|
|
80
|
+
"yes": "是",
|
|
81
|
+
"no": "否",
|
|
82
|
+
"origin": {
|
|
83
|
+
"local": "本站",
|
|
84
|
+
"wecom": "企业微信",
|
|
85
|
+
"ldap": "LDAP",
|
|
86
|
+
"sso": "SSO"
|
|
87
|
+
},
|
|
88
|
+
"columns": {
|
|
89
|
+
"name": "部门名称",
|
|
90
|
+
"nameEn": "英文名",
|
|
91
|
+
"parent": "上级部门"
|
|
92
|
+
},
|
|
93
|
+
"memberColumns": {
|
|
94
|
+
"user": "用户",
|
|
95
|
+
"main": "主部门",
|
|
96
|
+
"leader": "负责人",
|
|
97
|
+
"actions": "操作"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
53
100
|
"oplog": {
|
|
54
101
|
"filterAction": "操作 (action)",
|
|
55
102
|
"filterUsername": "用户名(前缀匹配)",
|
|
@@ -93,7 +140,8 @@
|
|
|
93
140
|
"env": "环境",
|
|
94
141
|
"status": "状态",
|
|
95
142
|
"installedAt": "开通时间",
|
|
96
|
-
"action": "操作"
|
|
143
|
+
"action": "操作",
|
|
144
|
+
"authMode": "授权模式"
|
|
97
145
|
},
|
|
98
146
|
"statusActive": "启用",
|
|
99
147
|
"statusDisabled": "停用",
|
|
@@ -103,7 +151,61 @@
|
|
|
103
151
|
"enable": "启用",
|
|
104
152
|
"disableConfirm": "停用该应用?企业成员将无法用它登录。",
|
|
105
153
|
"enableConfirm": "启用该应用?",
|
|
106
|
-
"empty": "暂无已开通企业"
|
|
154
|
+
"empty": "暂无已开通企业",
|
|
155
|
+
"authModeAdmin": "管理员授权",
|
|
156
|
+
"authModeMember": "成员授权",
|
|
157
|
+
"authModeHint": "「成员授权」模式下应用没有通讯录权限,该企业的组织架构无法同步——需企业管理员在企微后台改为「管理员授权」后重新授权。",
|
|
158
|
+
"sync": {
|
|
159
|
+
"updatedAt": "企微组织架构更新于 {{time}}",
|
|
160
|
+
"neverSynced": "尚未同步过企微组织架构",
|
|
161
|
+
"auto": "自动同步",
|
|
162
|
+
"syncNow": "立即同步",
|
|
163
|
+
"retry": "重试",
|
|
164
|
+
"resume": "继续同步",
|
|
165
|
+
"cancel": "取消同步",
|
|
166
|
+
"syncing": "正在读取企微组织架构…",
|
|
167
|
+
"syncingProgress": "正在同步:已处理 {{done}}/{{total}} 个部门",
|
|
168
|
+
"done": "同步完成:{{depts}} 个部门 / {{members}} 名成员",
|
|
169
|
+
"paused": "同步已暂停(已处理 {{depts}} 个部门),点「继续同步」接着往下",
|
|
170
|
+
"skipped": "{{count}} 个部门因权限被跳过(可见范围外的部门属正常)",
|
|
171
|
+
"cancelled": "已取消同步",
|
|
172
|
+
"ago": {
|
|
173
|
+
"justNow": "刚刚",
|
|
174
|
+
"minutes": "{{count}} 分钟前",
|
|
175
|
+
"hours": "{{count}} 小时前",
|
|
176
|
+
"days": "{{count}} 天前"
|
|
177
|
+
},
|
|
178
|
+
"memberAuth": {
|
|
179
|
+
"title": "该企业为「成员授权」模式,应用没有通讯录权限",
|
|
180
|
+
"hint": "请企业管理员在企微后台把授权模式改为「管理员授权」后重新授权,才能同步组织架构。"
|
|
181
|
+
},
|
|
182
|
+
"frozen": {
|
|
183
|
+
"title": "该企业已取消授权或应用已停用,同步已冻结",
|
|
184
|
+
"hint": "下方为最后一次同步的数据快照;请联系服务商重新开通后再同步。"
|
|
185
|
+
},
|
|
186
|
+
"err": {
|
|
187
|
+
"permission": {
|
|
188
|
+
"title": "应用缺少通讯录权限(错误码 {{code}})",
|
|
189
|
+
"hint": "企业管理员:企微后台 → 应用管理 → 本应用 → 权限,勾选「通讯录」相关权限并提交。"
|
|
190
|
+
},
|
|
191
|
+
"rateLimited": {
|
|
192
|
+
"title": "企微接口限流(错误码 {{code}})",
|
|
193
|
+
"hint": "已自动退避,稍后点「继续同步」即可。"
|
|
194
|
+
},
|
|
195
|
+
"ipWhitelist": {
|
|
196
|
+
"title": "服务器出口 IP 不在企微白名单(错误码 {{code}})",
|
|
197
|
+
"hint": "由服务商运维在企微后台补充可信 IP。"
|
|
198
|
+
},
|
|
199
|
+
"network": {
|
|
200
|
+
"title": "无法连接企业微信({{code}})",
|
|
201
|
+
"hint": "请检查服务器网络与企微接口可达性后重试。"
|
|
202
|
+
},
|
|
203
|
+
"unknown": {
|
|
204
|
+
"title": "同步失败(错误码 {{code}})",
|
|
205
|
+
"hint": "请联系服务商排查后重试。"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
107
209
|
},
|
|
108
210
|
"err": {
|
|
109
211
|
"forbidden": "无权限",
|
|
@@ -125,5 +227,9 @@
|
|
|
125
227
|
"ldap_base_dn": "LDAP Base DN",
|
|
126
228
|
"ldap_uid_attr": "LDAP UID 属性",
|
|
127
229
|
"ldap_email_attr": "LDAP 邮箱属性"
|
|
230
|
+
},
|
|
231
|
+
"perm": {
|
|
232
|
+
"platform_org_read_all": "组织架构全量读权限",
|
|
233
|
+
"auth_wecom_sync": "企业微信组织架构同步"
|
|
128
234
|
}
|
|
129
235
|
}
|