diff --git a/public/svg/auths/authed.svg b/public/svg/auths/authed.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c59b1300daac5f332d0a36646084a1d3a8fad397
--- /dev/null
+++ b/public/svg/auths/authed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/svg/auths/unauth.svg b/public/svg/auths/unauth.svg
new file mode 100644
index 0000000000000000000000000000000000000000..62b5181ceb0440b9fb6fe51c21f3838c85e2caf6
--- /dev/null
+++ b/public/svg/auths/unauth.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/Common/GlobalComps/entityIcon.module.less b/src/components/Common/GlobalComps/entityIcon.module.less
new file mode 100644
index 0000000000000000000000000000000000000000..17bcf8286cfdfdcf261e263e969bc4e9fa9aeb5a
--- /dev/null
+++ b/src/components/Common/GlobalComps/entityIcon.module.less
@@ -0,0 +1,12 @@
+.avatar_wapper {
+ position: relative;
+}
+
+.avatar_wapper .auth_icon {
+ position: absolute;
+ right: -3px;
+ bottom: -3px;
+ width: 15px;
+ height: 15px;
+ z-index: 99;
+}
diff --git a/src/components/Common/GlobalComps/entityIcon.tsx b/src/components/Common/GlobalComps/entityIcon.tsx
index 690500c4c78c1115b112d0abc64720a1222c7ce2..f5d5e0c07fd2c1e213729a7683bc2a167e5378f1 100644
--- a/src/components/Common/GlobalComps/entityIcon.tsx
+++ b/src/components/Common/GlobalComps/entityIcon.tsx
@@ -7,6 +7,7 @@ import TypeIcon from './typeIcon';
import useAsyncLoad from '@/hooks/useAsyncLoad';
import { ImInfo } from 'react-icons/im';
import { IBelong } from '@/ts/core';
+import style from './entityIcon.module.less';
import { TemplateType } from '@/ts/core/public/enums';
import { isSnowflakeId } from '@/ts/base/common';
@@ -19,6 +20,7 @@ interface teamTypeInfo {
title?: string;
showName?: boolean;
disableInfo?: boolean;
+ showAuthIcon?: boolean;
onClick?: (entity?: schema.XEntity) => void;
belong?: IBelong;
showImInfo?: boolean;
@@ -30,6 +32,16 @@ interface shareIconInfo extends teamTypeInfo {
share?: ShareIcon;
}
+const renderAuthIcon = (item: any) => {
+ const authed = item?.authenticated;
+ const shouldShowIcon =
+ item?.share?.typeName === '人员' || item?.share?.typeName === '单位';
+ const iconSrc = authed
+ ? `/svg/auths/authed.svg?v=1.0.0`
+ : `/svg/auths/unauth.svg?v=1.0.0`;
+ return shouldShowIcon &&
;
+};
+
/** 实体图标 */
const EntityIcon = (info: teamTypeInfo) => {
const getEntity = () => {
@@ -137,7 +149,8 @@ export const ShareIconItem = (info: shareIconInfo) => {
title={info.title ?? ''}
onClick={() => info.onClick?.apply(this, [info.entity])}>
{infoMore()}
-
+
+ {renderAuthIcon(info)}
{
style={{ display: 'flex', cursor: 'pointer' }}
onClick={() => info.onClick?.apply(this, [info.entity])}>
{infoMore()}
-
+
+ {renderAuthIcon(info)}
{icon}
{info.showName && (
diff --git a/src/components/DataPreview/session/index.tsx b/src/components/DataPreview/session/index.tsx
index 81619353ada0bc9831a6fe5297ecb7a91b32b98a..572fe12bea529518b1f3f7e04f90f6de708fdd22 100644
--- a/src/components/DataPreview/session/index.tsx
+++ b/src/components/DataPreview/session/index.tsx
@@ -9,9 +9,11 @@ import ChatBody from './chat';
import PreviewLayout from '../layout';
import { cleanMenus } from '@/utils/tools';
import useCtrlUpdate from '@/hooks/useCtrlUpdate';
+import { PrivateInfoCard } from './settingInfo/privateInfo';
import Setting from './setting';
import useAsyncLoad from '@/hooks/useAsyncLoad';
import { Spin } from 'antd';
+
const SessionBody = ({
session,
relation,
@@ -27,7 +29,7 @@ const SessionBody = ({
if (session.target.members.length < 30) {
await session.target.loadMembers(false);
}
- },[session]);
+ }, [session]);
useEffect(() => {
const newActions = [
{
@@ -86,39 +88,42 @@ const SessionBody = ({
}
}, [target, filter]);
return (
- {loaded &&
- { }}
- contextMenu={(entity) => {
- const file = (entity as IFile) || target.memberDirectory;
- return {
- items: cleanMenus(loadFileMenus(file)) || [],
- onClick: ({ key }: { key: string }) => {
- if (key === 'joinFriend') {
- command.emitter('executor', key, target);
- } else {
- command.emitter('executor', key, file);
- }
- },
- };
- }}
- onScrollEnd={async () => {
- if (target.memberFilterCount > target.members.length) {
- await target.loadMembers(false, filter);
- setContent([...target.memberDirectory.content()])
- }
- }}
- onFilter={async (value) => {
- setFilter(value);
- await target.loadMembers(false, value);
- setContent([...target.memberDirectory.content()])
- }}
- />}
+
+ {loaded && (
+ { }}
+ contextMenu={(entity) => {
+ const file = (entity as IFile) || target.memberDirectory;
+ return {
+ items: cleanMenus(loadFileMenus(file)) || [],
+ onClick: ({ key }: { key: string }) => {
+ if (key === 'joinFriend') {
+ command.emitter('executor', key, target);
+ } else {
+ command.emitter('executor', key, file);
+ }
+ },
+ };
+ }}
+ onScrollEnd={async () => {
+ if (target.memberFilterCount > target.members.length) {
+ await target.loadMembers(false, filter);
+ setContent([...target.memberDirectory.content()]);
+ }
+ }}
+ onFilter={async (value) => {
+ setFilter(value);
+ await target.loadMembers(false, value);
+ setContent([...target.memberDirectory.content()]);
+ }}
+ />
+ )}
+
);
};
@@ -133,7 +138,24 @@ const SessionBody = ({
case 'relation':
return ;
case 'setting': {
- return ;
+ return (
+ <>
+ {relation ? (
+
+ ) : (
+ <>>
+ )}
+
+ >
+ );
}
default:
return <>>;
diff --git a/src/components/DataPreview/session/settingInfo/index.tsx b/src/components/DataPreview/session/settingInfo/index.tsx
deleted file mode 100644
index 1edc011012b4c3decf98467f56608d9b7a69206b..0000000000000000000000000000000000000000
--- a/src/components/DataPreview/session/settingInfo/index.tsx
+++ /dev/null
@@ -1,438 +0,0 @@
-import React, { useRef, useState } from 'react';
-import orgCtrl from '@/ts/controller';
-import WorkFormViewer from '@/components/DataStandard/WorkForm/Viewer';
-import OpenFileDialog from '@/components/OpenFileDialog';
-import { ISession, IForm, ITarget, IFile, XCollection } from '@/ts/core';
-import { Button, Card } from 'antd';
-import { Xbase } from '@/ts/base/schema';
-import useAsyncLoad from '@/hooks/useAsyncLoad';
-import { Form } from '@/ts/core/thing/standard/form';
-import FullScreenModal from '@/components/Common/fullScreen';
-import { DataResource } from '@/ts/core/thing/resource';
-import FormService from '@/ts/scripting/core/services/FormService';
-
-export type InfoID = {
- // 信息名称
- InfoTypeName: string;
- // 信息的表单
- InfoFormID: string;
-} & Xbase;
-
-interface ICardProps {
- //权限
- auth: Array;
- //信息名称
- title: string;
- //信息存储的空间
- space: ITarget;
- //当前查看的对象
- target?: ITarget;
-}
-
-export type IContentProps = {
- InfoTypeName: string;
- targetID: string;
-} & Xbase & { [key: string]: any };
-// 用于创建自定义集合
-const collName = '-resource-info';
-const contentCollName = '-resource-content';
-
-interface ISettingInfoEntity {
- space: ITarget;
- coll: XCollection;
- title: string;
- form: IForm | undefined;
- contentColl: XCollection | undefined;
- content: IContentProps | undefined;
-}
-//设置信息实体
-class SettingInfoEntity implements ISettingInfoEntity {
- space: ITarget;
- coll: XCollection;
- title: string;
- form: IForm | undefined;
- contentColl: XCollection | undefined;
- content: IContentProps | undefined;
- infoId: InfoID | undefined;
- changeValue: any;
- resource: DataResource;
- constructor(space: ITarget, title: string) {
- this.space = space;
-
- let resource = this.space.resource;
- if (!resource) {
- resource = new DataResource(this.space.metadata, [], [this.space.metadata.id]);
- }
- this.resource = resource;
- this.coll = resource.genColl(collName);
- this.contentColl = resource.genColl(contentCollName);
- this.title = title;
- }
-
- async loadForm(): Promise {
- const res = await this.coll.load({});
- const targetInfoId = res.findLast((infoId) => {
- return infoId.InfoTypeName == this.title;
- });
-
- if (targetInfoId) {
- this.infoId = targetInfoId;
-
- const formArr = await this.resource.formColl.find([targetInfoId?.InfoFormID]);
- if (formArr[0]) {
- const formInst = new Form(
- { ...formArr[0], id: formArr[0].id + '_' },
- this.space.directory,
- );
- await formInst.loadFields();
- this.form = formInst;
- this.contentColl = this.resource.genColl(
- this.form.metadata.collName || '_system-things',
- );
- }
- }
- }
-
- async changeForm(form: IForm): Promise {
- if (this.infoId) {
- this.infoId.InfoFormID = form.id;
- await this.coll.update(this.infoId.id, {
- _set_: {
- InfoTypeName: this.infoId.InfoTypeName,
- InfoFormID: this.infoId.InfoFormID,
- },
- });
- } else {
- const data = {
- InfoTypeName: this.title,
- InfoFormID: form.id,
- };
- await this.coll.insert(data as unknown as InfoID);
- }
- }
-
- async loadInfo(target: ITarget): Promise {
- // 使用新的集合去存储表单的数据
- if (this.contentColl) {
- const res = await this.contentColl.load({});
- const typeContentArr = res.filter((data) => {
- return data.InfoTypeName == this.title;
- });
- const content = typeContentArr.find((data) => {
- return data.targetID === target.id;
- });
- if (!content) {
- const newContent = {
- InfoTypeName: this.title,
- targetID: target.id,
- labels: ['F' + this.form?.id],
- name: this.form?.name,
- };
- this.content = await this.contentColl.insert(
- newContent as unknown as IContentProps,
- );
- } else {
- this.content = content;
- }
- return this.getContentValue();
- }
- }
-
- getContentValue() {
- if (this.content) {
- const data: { [key: string]: any } = {};
- if (this.form?.fields) {
- this.form.fields.forEach((fieldId) => {
- if (this.content![fieldId.code]) {
- data[fieldId.id] = this.content![fieldId.code];
- }
- });
- }
- return data;
- }
- }
-
- setContentValue() {}
-
- changeContent(data: any) {
- this.changeValue = data;
- }
-
- async saveInfo(): Promise {
- if (this.content) {
- const saveData: { [key: string]: any } = {};
- for (let key in this.changeValue) {
- if (this.changeValue[key] && key !== 'name') {
- saveData['T' + key] = this.changeValue[key];
- }
- }
- if (this.contentColl) {
- await this.contentColl.update(this.content?.id, {
- _set_: { ...saveData },
- });
- }
- }
- }
-}
-
-const InfoCard: React.FC = (props) => {
- const { space, target, title } = props;
- // 表单选择器开关
- const [needType, setNeedType] = useState('');
- // 选定的表单
- const [form, setForm] = useState(undefined);
-
- const [formData, setFormData] = useState(undefined);
- const [infoEntity] = useState(new SettingInfoEntity(space, title));
- const server = useRef();
- const setAuth = props.auth.indexOf('set') > -1;
- const editAuth = props.auth.indexOf('edit') > -1;
- const previewAuth = props.auth.indexOf('preview') > -1;
- // 使用useAsyncLoad 加载表单的信息
- useAsyncLoad(async () => {
- await loadForm();
- if (previewAuth) {
- await loadInfo();
- }
- });
-
- // 加载信息绑定的表单
- const loadForm = async () => {
- // await infoEntity.loadForm();
- // setForm(infoEntity.form);
- };
-
- // 加载信息
- const loadInfo = async () => {
- // setFormData(await infoEntity.loadInfo(target || space));
- };
- // 设置信息
- const setInfo = (fieldId: string, value: any, data: any) => {
- // infoEntity.changeContent(data);
- };
- // 保存信息
- const saveInfo = async () => {
- // await infoEntity.saveInfo();
- };
-
- const getButtons = () => {
- const bottonArr = [];
- if (setAuth)
- bottonArr.push(
- ,
- );
- return bottonArr;
- };
- const getContent = () => {
- //根据权限 数据 当前选择切换展示的信息
- return (
- <>
-
- >
- );
- };
- const onSelectFinish = async (files: IFile[]) => {
- if ('表单' == needType) {
- const form = files[0] as IForm;
- await form.loadFields();
- setForm(form);
- server.current = FormService.fromIForm(form);
- // infoEntity.changeForm(form);
- }
- setNeedType('');
- };
- return (
- <>
-
- {getContent()}
-
-
- {form && server.current && (
- {
- setNeedType('');
- }}>
-
-
- )}
-
- {needType == '表单' && (
- setNeedType('')}
- onOk={onSelectFinish}
- />
- )}
- >
- );
-};
-
-interface IProps {
- target: ITarget;
- session: ISession;
-}
-
-const SettingInfoArr: React.FC = (props) => {
- const { target, session } = props;
- // 本人对象
- const mySelf = orgCtrl.user;
-
- //
- const arr = [];
- // 群权限
- const hasRelationAuth = session.target.hasRelationAuth();
- // 基本信息-公开信息
- // const reloadFinish = () => {
- // orgCtrl.changCallback();
- // };
- // arr.push(
- //
- // {/* */}
- // ,
- // );
-
- // 基本信息-备注信息
- let lastItemAuth = ['edit', 'preview'];
-
- // 对象类型
- switch (target.typeName) {
- case '人员':
- if (session.typeName == '人员') {
- if (target.metadata.id === orgCtrl.user.id) {
- // 本人
- lastItemAuth = ['set'];
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- // arr.push();
- } else {
- // 好友
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- }
- } else if (session.typeName == '单位') {
- // 同事
- arr.push(
- ,
- );
- if (hasRelationAuth)
- arr.push(
- ,
- );
- }
- break;
- case '单位':
- if (hasRelationAuth) {
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- } else {
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- arr.push(
- ,
- );
- }
- break;
- default:
- break;
- }
- const lastItem = (
-
- );
- arr.push(lastItem);
-
- return <>{arr}>;
-};
-
-export default SettingInfoArr;
diff --git a/src/components/DataPreview/session/settingInfo/privateInfo/PrivateInfo.ts b/src/components/DataPreview/session/settingInfo/privateInfo/PrivateInfo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..50485c8841e746c25df346cb424016ff7846c4ce
--- /dev/null
+++ b/src/components/DataPreview/session/settingInfo/privateInfo/PrivateInfo.ts
@@ -0,0 +1,540 @@
+import { ITarget, XCollection } from '@/ts/core';
+import { DataResource } from '@/ts/core/thing/resource';
+import { XTarget, Xbase } from '@/ts/base/schema';
+import {
+ personApplyFields,
+ organizationApplyFields,
+ personFields,
+ organizationFields,
+} from './fixFormField';
+import { LoadOptions } from '@/ts/base/model';
+import { model } from '@/ts/base';
+
+const personKeys = ['name', 'phoneNumber', 'identificationNumber'];
+const organizationKeys = [
+ 'organizationName',
+ 'orgldentificationType',
+ 'orgldentificationNumber',
+ 'name',
+ 'identificationType',
+ 'identificationNumber',
+];
+
+const collName = '-resource-privateinfomation';
+type information = Xbase & { [key: string]: any };
+
+/**
+ * 信息管理
+ */
+class BaseInfoManager {
+ /**
+ * 自定义的集合 用于存储所有相关数据
+ */
+ private coll: XCollection;
+ /**
+ * 缓存的所有数据
+ */
+ private res?: information[];
+ // private space: DataResource;
+ constructor(space: DataResource) {
+ this.coll = space.genColl(collName);
+ // this.space = space;
+ }
+
+ /**
+ * 加载信息并选择是否过滤掉已删除的数据
+ * @param options 过滤的规则
+ * @returns
+ */
+ private async getInfoByOptions(options: LoadOptions, filtDeleted = true) {
+ return (await this.coll.load({ options })).filter(
+ (item) => item.isDeleted != filtDeleted,
+ );
+ }
+
+ /**
+ * 获得单类型的数据
+ * @param infoType 信息类型 PrivateInfo JoinInfo joinApplyInfo
+ */
+ async getInfoByInfoType(infoType: string) {
+ const options = {
+ match: {
+ infoType,
+ },
+ } as LoadOptions;
+ return this.getInfoByOptions(options);
+ }
+ /**
+ * 获得单类型的最后一条
+ * @param infoType 信息类型 PrivateInfo JoinInfo
+ * @returns
+ */
+ async getLastInfoByInfoType(infoType: string) {
+ const res = await this.getInfoByInfoType(infoType);
+ if (res.length > 0) {
+ return res[res.length - 1];
+ }
+ }
+
+ /**
+ * 获得多类型类型的数据
+ * @param infoTypes 类型组
+ */
+ async getInfoByInfoTypes(infoTypes: string[]) {
+ const options = {
+ match: {
+ infoType: {
+ _in_: infoTypes,
+ },
+ },
+ } as LoadOptions;
+
+ return this.getInfoByOptions(options);
+ }
+
+ /**
+ * @param infoType 信息的类型
+ * @param data 存储的数据
+ * @returns
+ */
+ async createInfo(infoType: string, data: { [key: string]: any }) {
+ data['infoType'] = infoType;
+ let res;
+ try {
+ res = await this.coll.insert(data as unknown as information);
+ } catch (e) {
+ console.log(e);
+ }
+
+ return res;
+ }
+ /**
+ *
+ * @param id 信息的id
+ * @param data 要更新的部分
+ * @returns
+ */
+ async upDate(id: string, data: { [key: string]: any }) {
+ const res = await this.coll.update(id, data);
+ return res;
+ }
+
+ /**
+ * 测试方法用于删除开发中产生的数据
+ */
+ async deleltAllInfo() {
+ if (this.res) {
+ const res = await this.coll.deleteMany(this.res);
+ console.log('deleteAllInfo:', res);
+ }
+ }
+}
+/**
+ *设置页面个人单位隐私信息管理器
+ */
+export class SettingInfoManager {
+ /**
+ * 信息管理器
+ */
+ private infoManager: BaseInfoManager;
+ /**
+ * 信息存储的空间
+ */
+ private space: DataResource;
+
+ /**
+ * 是否有写入的权限
+ */
+ private auth;
+
+ public privateInfoFields: model.FieldModel[];
+ public joinInfoFields: model.FieldModel[];
+
+ /**
+ * 个人、单位隐私的信息
+ */
+ public privateInfo?: information;
+ /**
+ * 加入的要求填写的信息
+ */
+ public joinInfo?: information;
+
+ constructor(space: DataResource, auth: boolean) {
+ this.infoManager = new BaseInfoManager(space);
+ this.space = space;
+ this.auth = auth;
+ const sTarget = this.space.targetMetadata;
+ this.privateInfoFields =
+ sTarget.typeName === '人员' ? personFields : organizationFields;
+ this.joinInfoFields = personApplyFields;
+ if (['组织群'].indexOf(sTarget.typeName) > -1) {
+ this.joinInfoFields = organizationApplyFields;
+ }
+ }
+ /**
+ * 初始化信息 加载基础的两个数据
+ */
+
+ async init() {
+ await this.getPrivateInfo();
+ await this.getJoinInfo();
+ }
+
+ // 获取该空间下的隐私信息 如果不为 人员 或者单位则返回空
+ private async getPrivateInfo() {
+ let res = await this.infoManager.getLastInfoByInfoType('PrivateInfo');
+ if (!res && this.auth) {
+ // 当类型为人员、单位时根据系统信息创建信息
+ const newData = this.getSystemData();
+ switch (this.space.targetMetadata.typeName) {
+ case '人员':
+ res = await this.infoManager.createInfo('PrivateInfo', newData);
+ break;
+ case '单位':
+ res = await this.infoManager.createInfo('PrivateInfo', newData);
+ break;
+ }
+ }
+ this.privateInfo = res;
+ return this.privateInfo;
+ }
+ // 获取系统的信息
+ private getSystemData() {
+ const sTarget = this.space.targetMetadata;
+ const data: { [key: string]: any } = {};
+ switch (sTarget.typeName) {
+ case '人员':
+ data['name'] = sTarget.name;
+ data['phoneNumber'] = sTarget.code;
+ break;
+ case '单位':
+ data['organizationName'] = sTarget.name;
+ data['orgldentificationNumber'] = sTarget.code;
+ break;
+ default:
+ }
+ return data;
+ }
+ // 获取该空间下的申请设定信息
+ private async getJoinInfo() {
+ let res = await this.infoManager.getLastInfoByInfoType('JoinInfo');
+ if (!res && this.auth) {
+ // 根据类型不同创建不同的初始数据
+ const data: { [key: string]: any } = {};
+ this.joinInfoFields.forEach((field) => {
+ data[field.code] = false;
+ });
+ res = await this.infoManager.createInfo('JoinInfo', data);
+ }
+
+ this.joinInfo = res;
+ return this.joinInfo;
+ }
+
+ /**
+ * 更新集合下信息
+ * @param infoType 类型有:PrivateInfo JoinInfo joinApplyInfo memberInfo
+ */
+ async updated(infoType: String, data?: { [key: string]: any }) {
+ switch (infoType) {
+ case 'PrivateInfo':
+ if (this.privateInfo) {
+ await this.infoManager.upDate(this.privateInfo.id, this.privateInfo);
+ }
+ break;
+ case 'JoinInfo':
+ if (this.joinInfo) await this.infoManager.upDate(this.joinInfo.id, this.joinInfo);
+ break;
+ case 'memberInfo':
+ if (data) await this.infoManager.upDate(data.id, data);
+ break;
+ }
+ }
+
+ /**
+ * 保存用户加入其他群时填写的信息
+ * @param applicant 申请人
+ * @param target 被申请人
+ * @param data 数据
+ */
+ async saveApllyInfo(applicant: XTarget, target: XTarget, data: { [key: string]: any }) {
+ if (data) {
+ data['applicantId'] = applicant.id;
+ data['targetId'] = target.id;
+ }
+ await this.infoManager.createInfo('joinApplyInfo', data);
+ }
+
+ /**
+ * 读取用户加入其他群时填写的信息
+ * @param target 被申请人
+ */
+ async loadApplyInfo(target: XTarget) {
+ // TODO 如果加了多次如何与办事匹配上
+ const res = await this.infoManager.getInfoByInfoType('joinApplyInfo');
+ return res.findLast((info) => {
+ return info['targetId'] == target.id;
+ });
+ }
+
+ /**
+ * 当通过加入审批时把信息存在集合中并设置类型为 memberInfo
+ * @param data
+ */
+ async saveMemberInfo(data: { [key: string]: any }) {
+ // 传入的信息过滤下
+ console.log('存下申请人信息');
+
+ const fields = this.getMemberInfoFileds();
+ const saveData: { [key: string]: any } = {};
+ fields?.forEach((field) => {
+ saveData[field.code] = data[field.code];
+ });
+ saveData['applicantId'] = data['applicantId'];
+ saveData['targetId'] = data['targetId'];
+ const res = await this.infoManager.createInfo('memberInfo', saveData);
+ console.log(res);
+ }
+
+ async loadMemberInfo(member: XTarget) {
+ const res = await this.infoManager.getInfoByInfoType('memberInfo');
+ return res.findLast((info) => info['applicantId'] == member.id);
+ }
+
+ /**
+ * 获取成员信息的固定属性字段
+ */
+ getMemberInfoFileds() {
+ const sTarget = this.space.targetMetadata;
+ let allFields = personFields;
+ if (['组织群'].indexOf(sTarget.typeName) > -1) {
+ allFields = organizationFields;
+ }
+
+ const fields = allFields.filter((field) => {
+ if (this.joinInfo) return this.joinInfo[field.code + '_isNeed'];
+ });
+ return fields;
+ }
+
+ async deleltAllInfo() {
+ await this.infoManager.deleltAllInfo();
+ }
+}
+
+/**
+ * 用于自定义信息的增改
+ */
+export class PrivateInfoManager {
+ private target: ITarget;
+ public coll: XCollection;
+ // 自身隐私数据
+ public data: { [key: string]: any };
+ private keys: Array;
+ // 其他加入设定数据
+ public joinData: { [key: string]: string };
+ private joinKeys: Array;
+
+ // 该数据集合
+ private res?: information[];
+ constructor(target: ITarget, space?: DataResource) {
+ this.target = target;
+ const resource =
+ space ||
+ this.target.resource ||
+ new DataResource(this.target.metadata, [], [this.target.metadata.id]);
+ this.coll = resource.genColl(collName);
+ this.data = {};
+ this.joinData = {};
+ switch (target.typeName) {
+ case '人员':
+ this.keys = personKeys;
+ this.joinKeys = personKeys;
+ break;
+ case '单位':
+ this.keys = organizationKeys;
+ this.joinKeys = personKeys;
+ break;
+ default:
+ this.keys = [];
+ this.joinKeys = [];
+ }
+ }
+
+ async getInfoByKeys() {
+ let data = await this.getInfoByKey('PrivateInfo');
+ if (data) {
+ this.data = data;
+ this.checkData();
+ }
+ data = await this.getInfoByKey('JoinInfo');
+ if (data) {
+ this.joinData = data;
+ }
+ }
+
+ async getInfoByKey(infoType: string) {
+ if (!this.res) this.res = await this.coll.load({});
+ const res = this.res;
+ const target = res.find((item) => {
+ return item.infoType && item.infoType == infoType;
+ });
+ if (target) {
+ return target;
+ } else {
+ const newInfo = await this.createInfoBykey(infoType);
+ return newInfo;
+ }
+ }
+
+ async createInfoBykey(infoType: string) {
+ const keys = infoType == 'PrivateInfo' ? this.keys : this.joinKeys;
+ const data: { [key: string]: any } = {};
+ keys.forEach((key) => {
+ data[key] = '';
+ if (infoType == 'JoinInfo') {
+ data[key] = 'false';
+ }
+ });
+ data['infoType'] = infoType;
+ const res = await this.coll.insert(data as unknown as information);
+ return res;
+ }
+
+ async changeByKey(infoType: String) {
+ console.log('更新信息');
+ const data = infoType == 'PrivateInfo' ? this.data : this.joinData;
+ if (data) {
+ const res = await this.coll.update(data.id, {
+ _set_: { ...data },
+ });
+ console.log(res);
+ }
+ }
+ // 自动拉拉取数据
+ checkData() {
+ switch (this.target.typeName) {
+ case '人员':
+ console.log(this.data['name'], this.data['name'] == '');
+ if (this.data['name'] == '') {
+ this.data['name'] = this.target.name;
+ }
+ if (this.data['phoneNumber'] == '') {
+ this.data['phoneNumber'] = this.target.code;
+ }
+ break;
+ case '单位':
+ if (this.data['organizationName'] == '') {
+ this.data['organizationName'] = this.target.name;
+ }
+ if (this.data['orgldentificationNumber'] === '') {
+ this.data['orgldentificationNumber'] = this.target.code;
+ }
+ break;
+ default:
+ this.keys = [];
+ }
+ }
+
+ getMemberInfo(target: XTarget) {
+ if (this.res) {
+ const memberInfo = this.res.findLast((item) => {
+ return (
+ item.infoType && item.infoType == 'memberInfo' && item.applicantId == target.id
+ );
+ });
+ return memberInfo;
+ }
+ }
+}
+
+export class JoinInfoManager {
+ public PIManager: PrivateInfoManager;
+ public data: { [key: string]: any };
+ constructor(space: ITarget, target: XTarget) {
+ console.log(space);
+ // const resource = new DataResource(space, [], [space.id]);
+ this.PIManager = new PrivateInfoManager(space);
+ this.data = {
+ targetId: target.id,
+ applicantId: space.id,
+ infoType: 'joinApplyInfo',
+ };
+ }
+
+ setData(key: string, value: any) {
+ this.data[key] = value;
+ }
+
+ async saveData(data?: any) {
+ if (data) {
+ data['targetId'] = this.data['targetId'];
+ data['applicantId'] = this.data['applicantId'];
+ data['infoType'] = this.data['infoType'];
+ }
+ console.log(data);
+
+ await this.PIManager.coll.insert(data || (this.data as unknown as information));
+ }
+}
+
+export class JoinInfoReader {
+ private PIManager: PrivateInfoManager;
+ /** 被申请者*/
+ public target: XTarget;
+ /** 申请者*/
+ private space: XTarget;
+ private TPIManager: PrivateInfoManager;
+ public applyData?: { [key: string]: string };
+ public requreData?: { [key: string]: string };
+
+ constructor(space: XTarget, target: XTarget) {
+ const resource = new DataResource(space, [], [space.id]);
+ this.PIManager = new PrivateInfoManager(space as any, resource);
+ const tResource = new DataResource(target, [], [target.id]);
+ this.TPIManager = new PrivateInfoManager(tResource as any, tResource);
+ this.target = target;
+ this.space = space;
+ }
+
+ /**
+ * 在申请者空间下找到申请时填写的信息
+ * 在被申请者空间下找到要求填写的信息
+ * @returns 返回找的申请时填写的信息
+ */
+ async getInfo() {
+ await this.PIManager.getInfoByKeys();
+ await this.TPIManager.getInfoByKeys();
+ const res = await this.PIManager.coll.load({});
+ const target = res.findLast((item) => {
+ return (
+ item.infoType &&
+ item.infoType == 'joinApplyInfo' &&
+ item.targetId == this.target.id &&
+ item.applicantId == this.space.id
+ );
+ });
+ this.applyData = target;
+ this.requreData = this.TPIManager.joinData;
+
+ return target;
+ }
+
+ // 审批通过时记录该信息
+ async saveInfo() {
+ // return this.TPIManager.coll.insert(this.target);
+ console.log(this.applyData);
+ const data: { [key: string]: string } = {};
+ if (this.applyData) {
+ for (let key in this.requreData) {
+ if (this.requreData[key] === 'true') data[key] = this.applyData[key];
+ }
+ data['targetId'] = this.applyData['targetId'];
+ data['applicantId'] = this.applyData['applicantId'];
+ data['infoType'] = 'memberInfo';
+ console.log(data);
+
+ return this.TPIManager.coll.insert(data as any);
+ }
+ }
+}
diff --git a/src/components/DataPreview/session/settingInfo/privateInfo/fixFormField.ts b/src/components/DataPreview/session/settingInfo/privateInfo/fixFormField.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1be0fbd4433417486ac7ede00243e2773508e92e
--- /dev/null
+++ b/src/components/DataPreview/session/settingInfo/privateInfo/fixFormField.ts
@@ -0,0 +1,191 @@
+import { model } from '@/ts/base';
+export const personFields: model.FieldModel[] = [
+ {
+ id: 'name',
+ name: '姓名',
+ code: 'name',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'phoneNumber',
+ name: '手机号',
+ code: 'phoneNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'identificationNumber',
+ name: '身份证',
+ code: 'identificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+];
+
+export const organizationFields: model.FieldModel[] = [
+ {
+ id: 'organizationName',
+ name: '企业名称',
+ code: 'organizationName',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'orgldentificationType',
+ name: '企业识别号类型',
+ code: 'orgldentificationType',
+ valueType: '选择型',
+ remark: '',
+ lookups: [
+ {
+ id: '',
+ code: '',
+ text: '企业注册号',
+ value: '10',
+ info: '',
+ },
+ {
+ id: '',
+ code: '',
+ text: '统一社会信用代码',
+ value: '20',
+ info: '',
+ },
+ ],
+ },
+ {
+ id: 'orgldentificationNumber',
+ name: '企业识别号码',
+ code: 'orgldentificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'name',
+ name: '法人姓名',
+ code: 'name',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'identificationType',
+ name: '法人证件类型',
+ code: 'identificationType',
+ valueType: '选择型',
+ remark: '',
+ lookups: [{ id: '', code: '', value: '0', text: '身份证', info: '' }],
+ },
+ {
+ id: 'identificationNumber',
+ name: '法人身份证件号码',
+ code: 'identificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+];
+
+const chooseLookUp = [
+ {
+ id: '',
+ code: '',
+ text: '要求填写',
+ value: true,
+ info: '',
+ },
+ {
+ id: '',
+ code: '',
+ text: '不要求填写',
+ value: false,
+ info: '',
+ },
+];
+
+export const personApplyFields: model.FieldModel[] = [
+ {
+ id: 'name_isNeed',
+ name: '姓名',
+ code: 'name_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'phoneNumber_isNeed',
+ name: '手机号',
+ code: 'phoneNumber_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'identificationNumber_isNeed',
+ name: '身份证',
+ code: 'identificationNumber_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+];
+
+export const organizationApplyFields: model.FieldModel[] = [
+ {
+ id: 'organizationName_isNeed',
+ name: '企业名称',
+ code: 'organizationName_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'orgldentificationType_isNeed',
+ name: '企业识别号类型',
+ code: 'orgldentificationType_isNeed',
+ valueType: '选择型',
+ widget: '单选框',
+
+ remark: '',
+ lookups: chooseLookUp,
+ },
+ {
+ id: 'orgldentificationNumber_isNeed',
+ name: '企业识别号码',
+ code: 'orgldentificationNumber_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'name_isNeed',
+ name: '法人姓名',
+ code: 'name_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'identificationType_isNeed',
+ name: '法人证件类型',
+ code: 'identificationType_isNeed',
+ valueType: '选择型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+ {
+ id: 'identificationNumber_isNeed',
+ name: '法人身份证件号码',
+ code: 'identificationNumber_isNeed',
+ valueType: '描述型',
+ widget: '单选框',
+ lookups: chooseLookUp,
+ remark: '',
+ },
+];
diff --git a/src/components/DataPreview/session/settingInfo/privateInfo/fixedForm.tsx b/src/components/DataPreview/session/settingInfo/privateInfo/fixedForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f0666ddc99df47158b2743f6c179c756012a4ec4
--- /dev/null
+++ b/src/components/DataPreview/session/settingInfo/privateInfo/fixedForm.tsx
@@ -0,0 +1,94 @@
+import FormItem from '@/components/DataStandard/WorkForm/Viewer/formItem';
+import { model } from '@/ts/base';
+import Toolbar, { Item } from 'devextreme-react/toolbar';
+import React from 'react';
+import { getItemNums } from '@/components/DataStandard/WorkForm/Utils';
+import useStorage from '@/hooks/useStorage';
+import { IBelong, ITarget } from '@/ts/core';
+
+interface IProps {
+ data: any;
+ fields: model.FieldModel[];
+
+ /**
+ * 信息的归属方
+ */
+ space: ITarget;
+ onValuesChange?: (field: string, value: any) => void;
+ onSetButtonClick?: () => void;
+ onSyncButtonClick?: () => void;
+ readOnly?: boolean;
+ //todo 加入类似插槽的 允许外部传入按钮 实现功能组合 例如同步隐私信息 同步系统信息等
+}
+
+/**
+ * 固定属性的表单数据展示
+ */
+export const FixedForm: React.FC = (props) => {
+ const [colNum, setColNum] = useStorage('workFormColNum', '一列');
+ return (
+ <>
+
+ {props.onSyncButtonClick && (
+
+ )}
+
+ {props.onSetButtonClick && (
+
+ )}
+ - {
+ setColNum(e.itemData);
+ },
+ }}
+ />
+
+
+ {props.fields.map((field) => {
+ // if (field.widget === '单选框') {
+ // console.log(11111);
+
+ // return ;
+ // }
+
+ return (
+
+ );
+ })}
+
+ >
+ );
+};
diff --git a/src/components/DataPreview/session/settingInfo/privateInfo/fixedFormItem.tsx b/src/components/DataPreview/session/settingInfo/privateInfo/fixedFormItem.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5ecfca83e210fde0fad29a0aee5c31c1255e903c
--- /dev/null
+++ b/src/components/DataPreview/session/settingInfo/privateInfo/fixedFormItem.tsx
@@ -0,0 +1,225 @@
+// import React, { useEffect, useState, createRef, useCallback } from 'react';
+import React from 'react';
+import { getWidget, getItemWidth } from '@/components/DataStandard/WorkForm/Utils';
+import {
+ // DropDownBox,
+ // DateBox,
+ // NumberBox,
+ SelectBox,
+ // TextArea,
+ TextBox,
+ // TreeView,
+} from 'devextreme-react';
+import { model } from '@/ts/base';
+
+export type FAttribute = {
+ // 名称
+ name: string;
+ // 编号
+ code: string;
+ // 特性显示组件
+ widget?: string;
+ // 用于校验的属性
+ rule?: string;
+ lookups?: FFiledLookup[];
+};
+
+export type FFiledLookup = {
+ /** 分类项值 */
+ value: string;
+ /** 描述(项名称) */
+ text: string;
+};
+
+export const personAttributes: FAttribute[] = [
+ {
+ name: '姓名',
+ code: 'name',
+ widget: '描述型',
+ },
+ {
+ name: '手机号',
+ code: 'phoneNumber',
+ widget: '描述型',
+ },
+ {
+ name: '身份证',
+ code: 'identificationNumber',
+ widget: '描述型',
+ },
+];
+
+export const personFields: model.FieldModel[] = [
+ {
+ id: 'name',
+ name: '姓名',
+ code: 'name',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'phoneNumber',
+ name: '手机号',
+ code: 'phoneNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'identificationNumber',
+ name: '身份证',
+ code: 'identificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+];
+
+export const organizationAttributes: FAttribute[] = [
+ {
+ name: '企业名称',
+ code: 'organizationName',
+ widget: '描述型',
+ },
+ {
+ name: '企业识别号类型',
+ code: 'orgldentificationType',
+ widget: '选择型',
+ // lookups: ['企业注册号', '统一社会信用代码'],
+ lookups: [
+ { value: '10', text: '企业注册号' },
+ { value: '20', text: '统一社会信用代码' },
+ ],
+ },
+ {
+ name: '企业识别号码',
+ code: 'orgldentificationNumber',
+ widget: '描述型',
+ },
+ {
+ name: '法人姓名',
+ code: 'name',
+ widget: '描述型',
+ },
+ {
+ name: '法人证件类型',
+ code: 'identificationType',
+ widget: '选择型',
+ lookups: [{ value: '0', text: '身份证' }],
+ },
+ {
+ name: '法人身份证件号码',
+ code: 'identificationNumber',
+ widget: '描述型',
+ },
+];
+
+export const organizationFields: model.FieldModel[] = [
+ {
+ id: 'organizationName',
+ name: '企业名称',
+ code: 'organizationName',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'orgldentificationType',
+ name: '企业识别号类型',
+ code: 'orgldentificationType',
+ valueType: '选择型',
+ remark: '',
+ lookups: [
+ {
+ id: '',
+ code: '',
+ text: '企业注册号',
+ value: '10',
+ info: '',
+ },
+ {
+ id: '',
+ code: '',
+ text: '统一社会信用代码',
+ value: '20',
+ info: '',
+ },
+ ],
+ },
+ {
+ id: 'orgldentificationNumber',
+ name: '企业识别号',
+ code: 'orgldentificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'name',
+ name: '法人姓名',
+ code: 'name',
+ valueType: '描述型',
+ remark: '',
+ },
+ {
+ id: 'identificationType',
+ name: '法人证件类型',
+ code: 'identificationType',
+ valueType: '选择型',
+ remark: '',
+ lookups: [{ id: '', code: '', value: '0', text: '身份证', info: '' }],
+ },
+ {
+ id: 'identificationNumber',
+ name: '法人身份证件号码',
+ code: 'identificationNumber',
+ valueType: '描述型',
+ remark: '',
+ },
+];
+
+interface Iprops {
+ attr: FAttribute;
+ defaultValue: any;
+ value?: any;
+ onValueChange: (value: any) => {};
+}
+
+const mixOptions: any = {
+ height: 36,
+ showClearButton: true,
+ width: getItemWidth('二列'),
+ showMaskMode: 'always',
+ labelMode: 'floating',
+ labelLocation: 'left',
+};
+
+export const FixedFormItem: React.FC = ({
+ attr,
+ defaultValue,
+ value,
+ onValueChange,
+}) => {
+ switch (getWidget(attr.widget)) {
+ case '文本框':
+ return (
+
+ );
+ case '单选框':
+ return (
+ onValueChange(value)}
+ {...mixOptions}
+ />
+ );
+ }
+};
diff --git a/src/components/DataPreview/session/settingInfo/privateInfo/index.tsx b/src/components/DataPreview/session/settingInfo/privateInfo/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..59a27103c1c27f5715065cba0b4ba1038910da07
--- /dev/null
+++ b/src/components/DataPreview/session/settingInfo/privateInfo/index.tsx
@@ -0,0 +1,265 @@
+import React, { useState } from 'react';
+import { useAsync } from 'react-use';
+import { kernel } from '@/ts/base';
+import QrCode from 'qrcode.react';
+import { ISession, ITarget } from '@/ts/core';
+import { Button, Card, message } from 'antd';
+import FullScreenModal from '@/components/Common/fullScreen';
+import { SettingInfoManager } from './PrivateInfo';
+import { FixedForm } from './fixedForm';
+import orgCtrl from '@/ts/controller';
+interface Iprops {
+ /**
+ * 发生的会话
+ */
+ session: ISession;
+ /**
+ * 在谁的空间下
+ */
+ space: ITarget;
+ /**
+ * 查看谁
+ */
+ target: ITarget;
+}
+
+// 通过 HTTP 请求发送认证相关数据
+function sendAuthData(
+ url: string,
+ data: Record,
+): Promise> {
+ return new Promise((ok, error) => {
+ const xhr = new XMLHttpRequest();
+ xhr.open('POST', url);
+ xhr.setRequestHeader('content-type', 'application/json');
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ if (xhr.status === 200) {
+ // 获取响应数据的原始文本内容
+ const rawText = xhr.responseText;
+ try {
+ ok(JSON.parse(rawText));
+ } catch (e) {
+ error('请求失败');
+ }
+ } else {
+ error('请求失败');
+ }
+ }
+ };
+ xhr.send(JSON.stringify(data));
+ });
+}
+
+function zlbFaceAuth(requestId: string, setQrcode: (url: string) => void): Promise {
+ const accessToken = kernel.accessToken;
+ return new Promise((ok, error) => {
+ const zlbInstance = new window._GovAuthentication({
+ accessKey: 'BCDSGA_c5c86d2c327e2a5d454dba9ab0fd718c',
+ requestId,
+ onlnited: function (url: string) {
+ setQrcode(url);
+ },
+ onVerifyResult: async function (result: Record) {
+ setQrcode('');
+
+ if (!result.pass) {
+ return error(result.msg);
+ }
+
+ // 认证成功
+ const verifyResult = await sendAuthData('/ZLB/Verify', {
+ RequestId: requestId,
+ AccessToken: accessToken,
+ });
+
+ if (!verifyResult.success) {
+ return error(verifyResult.message);
+ }
+
+ ok();
+ // console.log(
+ // await sendAuthData('/ZLB/IsVerify', {
+ // AccessToken: kernel.accessToken,
+ // }),
+ // );
+ },
+ });
+ zlbInstance.destroy();
+ });
+}
+
+export const PrivateInfoCard: React.FC = (props) => {
+ const [targetInfo, setTargetInfo] = useState<{ [key: string]: any }>();
+ const [didload, setDidload] = useState(false);
+ const [qrcode, setQrcode] = useState('');
+
+ // 权限与是否显示
+ const isSelf = props.space.id == props.target.id;
+ // 群权限
+ const hasRelationAuth = props.session.target.hasRelationAuth();
+
+ const showPrivateCard = ['人员', '单位'].indexOf(props.target.typeName) > -1;
+
+ const [SIManeger] = useState(
+ new SettingInfoManager(props.space.resource, hasRelationAuth),
+ );
+
+ useAsync(async () => {
+ try {
+ await SIManeger.init();
+ if (!isSelf) {
+ setTargetInfo(await SIManeger.loadMemberInfo(props.target.metadata));
+ } else {
+ setTargetInfo(await SIManeger.loadMemberInfo(orgCtrl.user.metadata));
+ }
+ } catch (e) {
+ console.log('获取信息失败:', e);
+ }
+ setDidload(true);
+ });
+
+ const getContentWithMyComponent = () => {
+ return (
+ {
+ if (SIManeger.privateInfo) {
+ SIManeger.privateInfo[field] = value;
+ await SIManeger.updated('PrivateInfo');
+ }
+ }}>
+ );
+ };
+
+ const getTargetMemberInfo = () => {
+ if (targetInfo) {
+ return (
+ <>
+ {
+ targetInfo[field] = value;
+ await SIManeger.updated('memberInfo', targetInfo);
+ }}
+ />
+ >
+ );
+ } else
+ return (
+ <>
+ 该成员暂无信息
+ >
+ );
+ };
+
+ const getJoinContent = () => {
+ return (
+ {
+ if (SIManeger.joinInfo) {
+ SIManeger.joinInfo[field] = value;
+ await SIManeger.updated('JoinInfo');
+ }
+ }}>
+ );
+ };
+
+ const identify = async () => {
+ switch (props.target.typeName) {
+ case '人员':
+ {
+ const res = await sendAuthData('/ZLB/GetRequestId', {
+ CertNo: SIManeger.privateInfo!.identificationNumber,
+ CertName: SIManeger.privateInfo!.name,
+ CertType: 1,
+ AccessToken: kernel.accessToken,
+ });
+ zlbFaceAuth(res.data, setQrcode)
+ .then(() => {})
+ .catch((errMsg) => message.error(errMsg));
+ }
+ break;
+ case '单位':
+ // TODO 认证接口的调用 尚未开发相应单位认证流程
+ break;
+ }
+ };
+ const getAllContent = () => {
+ if (isSelf) {
+ return (
+ <>
+ {showPrivateCard && hasRelationAuth && (
+ <>
+ {
+ await identify();
+ }}>
+ 认证
+
+ }>
+ {didload && <>{getContentWithMyComponent()}>}
+
+ {didload && <>{getJoinContent()}>}
+
+ {qrcode && (
+ setQrcode('')}>
+
+
+
+ 请使用浙里办App扫码进行人脸认证
+
+
+
+ )}
+ >
+ )}
+
+ {props.space.typeName == '单位' && (
+
+ {didload && <>{getTargetMemberInfo()}>}
+
+ )}
+ >
+ );
+ } else {
+ if (props.space.typeName == '单位')
+ return (
+ <>
+ {getTargetMemberInfo()}
+ >
+ );
+ else
+ return (
+ <>
+ {getTargetMemberInfo()}
+ >
+ );
+ }
+ };
+
+ return getAllContent();
+};
diff --git a/src/components/Directory/views/index.tsx b/src/components/Directory/views/index.tsx
index a00edcf7f954a41333277eabb0fc1ce392f8520c..0f544be82744c561df39a6b3a54f3159fba66940 100644
--- a/src/components/Directory/views/index.tsx
+++ b/src/components/Directory/views/index.tsx
@@ -26,6 +26,7 @@ interface IProps {
isMenu?: boolean;
isNav?: boolean;
isDynamic?: boolean;
+ showAuthTag?: boolean;
customTags?: { tag: string; count: number }[];
badgeCount?: (tag: string) => number;
tagChanged?: (tag: string) => void;
@@ -59,13 +60,13 @@ const DirectoryView: React.FC = (props) => {
const getContent = useCallback((filter: boolean = true) => {
const filters = filterText.split('$$').filter((item) => item && item.length > 1);
const filterExp = (file: IDEntity) => {
- return filters.length < 1 || filters.some((item) =>
- file.code?.includes(item) ||
- file.name.includes(item) ||
- file.remark.includes(item) ||
- file.typeName.includes(item) ||
- file.filterTags.filter((i) => i.includes(item)).length > 0 ||
- file.groupTags.filter((i) => i.includes(item)).length > 0);
+ return filters.length < 1 || filters.some((item) =>
+ file.code?.includes(item) ||
+ file.name.includes(item) ||
+ file.remark.includes(item) ||
+ file.typeName.includes(item) ||
+ file.filterTags.filter((i) => i.includes(item)).length > 0 ||
+ file.groupTags.filter((i) => i.includes(item)).length > 0);
};
if (props.extraTags) {
if (filter && props.currentTag == '已选中') {
@@ -133,6 +134,7 @@ const DirectoryView: React.FC = (props) => {
/>
) : (
{
const droppable = useRef(directory && directory.id != directory.target.id);
@@ -42,6 +44,15 @@ const ListMode = ({
return isMenu ? css.vlist_item : `${css.vlist_item} ${css.border_bottom}`;
};
+ const renderAuthIconNode = (item: any) => {
+ const authed = item.metadata?.authenticated;
+ return (
+ showAuthTag && (
+ {authed ? '已认证' : '未认证'}
+ )
+ );
+ };
+
const reorder = (list: IDEntity[], startIndex: number, endIndex: number) => {
const result = Array.from(list);
const removedItem = result.splice(startIndex, 1)[0];
diff --git a/src/executor/operate/joinTarget/index.tsx b/src/executor/operate/joinTarget/index.tsx
index d158bab8166682c24d8d9756c85021db1687335b..202dd2c27c5e9b420742e2e7b8554d33f63ceac9 100644
--- a/src/executor/operate/joinTarget/index.tsx
+++ b/src/executor/operate/joinTarget/index.tsx
@@ -3,7 +3,10 @@ import { XTarget } from '@/ts/base/schema';
import { IBelong, TargetType } from '@/ts/core';
import SearchTarget from '@/components/Common/SearchTarget';
import { Modal } from 'antd';
-import { schema } from '@/ts/base';
+import { model, schema } from '@/ts/base';
+import { SettingInfoManager } from '@/components/DataPreview/session/settingInfo/privateInfo/PrivateInfo';
+import { DataResource } from '@/ts/core/thing/resource';
+import { FixedForm } from '@/components/DataPreview/session/settingInfo/privateInfo/fixedForm';
import { logger } from '@/ts/base/common';
type IProps = {
@@ -17,8 +20,20 @@ type IProps = {
*/
const JoinTarget: React.FC = ({ cmd, current, finished }) => {
const [selectMembers, setSelectMembers] = useState([]); // 选中的要拉的人
+ const [showEditFormModal, setShowEditFormModal] = useState(false);
+ let useEditFormModal = true;
let modalTitle = '';
let selectTargetType: TargetType = TargetType.Person;
+
+ // 用于记录自己填写的信息
+ const [SIManager, setSIManager] = useState();
+
+ const [apllyData, setApllayData] = useState({});
+
+ const [fixedFields, setFixedFields] = useState([]);
+ // 同步信息个人 刷新表格
+ const [dataReloaded, setDataReloaded] = useState(true);
+
switch (cmd) {
case 'joinFriend':
modalTitle = '申请加好友';
@@ -30,6 +45,7 @@ const JoinTarget: React.FC = ({ cmd, current, finished }) => {
case 'joinStorage':
modalTitle = '申请加入存储资源群';
selectTargetType = TargetType.Storage;
+ useEditFormModal = false;
break;
case 'joinCompany':
modalTitle = '申请加入单位';
@@ -46,30 +62,107 @@ const JoinTarget: React.FC = ({ cmd, current, finished }) => {
default:
return <>>;
}
+ const finishApply = () => {
+ logger.info('申请成功!请等待审批...');
+ finished();
+ };
+
+ const OpenApplyInfo = async () => {
+ const resource = new DataResource(selectMembers[0], [], [selectMembers[0].id]);
+ // 申请加入对象的信息管理
+ const targetInfoManager = new SettingInfoManager(resource, false);
+ await targetInfoManager.init();
+ const needData = targetInfoManager.joinInfo;
+ const slefResource = new DataResource(current.metadata, [], [current.id]);
+ const selfInfoManager = new SettingInfoManager(slefResource, true);
+ await selfInfoManager.init();
+ if (needData) {
+ const fields: model.FieldModel[] = targetInfoManager.getMemberInfoFileds();
+ if (fields.length > 0) {
+ setFixedFields(fields);
+ setSIManager(selfInfoManager);
+ setShowEditFormModal(true);
+ return;
+ }
+ }
+ if (await current.applyJoin(selectMembers)) finishApply();
+ };
+
+ const getApplyInfoInput = () => {
+ return (
+ <>
+ {useEditFormModal && showEditFormModal && (
+ {
+ await SIManager?.saveApllyInfo(
+ current.metadata,
+ selectMembers[0],
+ apllyData,
+ );
+ await current.applyJoin(selectMembers);
+ finishApply();
+ }}>
+ {dataReloaded && (
+ {
+ apllyData[field] = value;
+ }}
+ onSetButtonClick={() => {
+ // 同步自身信息
+ setDataReloaded(false);
+ const data: { [key: string]: any } = {};
+ fixedFields.forEach((field) => {
+ if (SIManager?.privateInfo)
+ data[field.id] = SIManager?.privateInfo[field.id];
+ });
+ setApllayData(data);
+ setTimeout(() => {
+ setDataReloaded(true);
+ }, 10);
+ }}>
+ )}
+
+ )}
+ >
+ );
+ };
return (
- {
- if (await current.applyJoin(selectMembers)) {
- logger.info('申请成功!请等待审批...');
- finished();
- }
- }}
- onCancel={finished}
- okButtonProps={{ disabled: selectMembers.length < 1 }}
- width={670}>
- {
- setSelectMembers(persons);
- }}
- searchType={selectTargetType}
- belongId={modalTitle === '申请加入部门' ? current.belongId : undefined}
- code={modalTitle === '申请加入部门' ? current.metadata.code : undefined}
- />
-
+ <>
+ {
+ if (!useEditFormModal) {
+ if (await current.applyJoin(selectMembers)) finishApply();
+ } else {
+ await OpenApplyInfo();
+ }
+ }}>
+ {
+ setSelectMembers(persons);
+ }}
+ searchType={selectTargetType}
+ belongId={modalTitle === '申请加入部门' ? current.belongId : undefined}
+ code={modalTitle === '申请加入部门' ? current.metadata.code : undefined}
+ />
+
+ {getApplyInfoInput()}
+ >
);
};
diff --git a/src/executor/tools/task/joinApply/index.tsx b/src/executor/tools/task/joinApply/index.tsx
index 78cd94883232681986154f243ead45344377e627..d0112a4425a9de35a32dc1a9ae3ddfdfc5be029e 100644
--- a/src/executor/tools/task/joinApply/index.tsx
+++ b/src/executor/tools/task/joinApply/index.tsx
@@ -1,11 +1,15 @@
-import React from 'react';
-import { IWorkTask, TaskStatus } from '@/ts/core';
+import React, { useState } from 'react';
+import { ITarget, IWorkTask, TaskStatus } from '@/ts/core';
import EntityIcon from '@/components/Common/GlobalComps/entityIcon';
import { Divider, Space, Timeline, Card, Tabs } from 'antd';
import { formatZhDate } from '@/utils/tools';
import TaskApproval from '@/executor/tools/task/approval';
import { command } from '@/ts/base';
import cls from './index.module.less';
+import { useAsync } from 'react-use';
+import { SettingInfoManager } from '@/components/DataPreview/session/settingInfo/privateInfo/PrivateInfo';
+import { FixedForm } from '@/components/DataPreview/session/settingInfo/privateInfo/fixedForm';
+import { DataResource } from '@/ts/core/thing/resource';
export interface TaskDetailType {
current: IWorkTask;
@@ -13,6 +17,27 @@ export interface TaskDetailType {
const TaskContent: React.FC = ({ current }) => {
if (current.targets.length < 2) return <>>;
+ const [AIManager] = useState(
+ new SettingInfoManager(
+ new DataResource(current.targets[0], [], [current.targets[0].id]),
+ false,
+ ),
+ );
+ const [SIManager] = useState(
+ new SettingInfoManager(
+ new DataResource(current.targets[1], [], [current.targets[1].id]),
+ true,
+ ),
+ );
+ const [apllyData, setApllayData] = useState<{ [key: string]: any }>();
+
+ useAsync(async () => {
+ await SIManager.init();
+ const res = await AIManager.loadApplyInfo(current.targets[1]);
+ if (res) {
+ setApllayData(res);
+ }
+ });
/** 加载时间条 */
const loadTimeline = () => {
@@ -36,6 +61,17 @@ const TaskContent: React.FC = ({ current }) => {
申请加入
+ {apllyData && (
+ <>
+ 申请人信息:
+
+ >
+ )}
+
申请时间:{formatZhDate(current.taskdata.createTime)}
{current.taskdata.records && current.taskdata.records.length > 0 && (
<>
@@ -63,8 +99,11 @@ const TaskContent: React.FC = ({ current }) => {
{
+ finished={async () => {
command.emitter('preview', 'work');
+ if (apllyData) {
+ await SIManager.saveMemberInfo(apllyData);
+ }
}}
/>
diff --git a/src/pages/Relation/index.tsx b/src/pages/Relation/index.tsx
index 5b13fed2c2935ff6bd0619b4db533214de5fdb1c..124a280f824ba9688e4679de68a2dc92557f0191 100644
--- a/src/pages/Relation/index.tsx
+++ b/src/pages/Relation/index.tsx
@@ -126,6 +126,7 @@ const RelationBrowser: React.FC = () => {
{renderHeader()}
{
// 报表树子节点
export type ReportTreeNodeView = WithChildren;
-export interface ReportTaskTreeNodeView extends XReportTaskTreeNode {
+export interface ReportTaskTreeNodeView extends XReportTreeNode {
+ // 子节点
children: ReportTaskTreeNodeView[];
+ reception?: XReception | null;
count: number;
isLeaf: boolean;
}
@@ -2148,6 +2133,40 @@ export interface ReportTreeNode extends XReportTreeNode {
index: number;
}
+interface AuthResponse {
+ responseCode?: string;
+ responseMessage?: string;
+ verification?: boolean;
+}
+export interface componyAuthReqType {
+ organizationName: string;
+ orgIdentificationType: string;
+ orgIdentificationNumber: string;
+ name: string;
+ identificationType: string;
+ identificationNumber: string;
+ remark?: string;
+}
+
+export interface componyAuthResType {
+ code?: number;
+ message?: string;
+ result?: AuthResponse;
+}
+export interface personAuthReqType {
+ identificationType?: string;
+ identificationNumber: string;
+ name: string;
+ phoneNumber: string;
+ remark?: string;
+}
+
+export interface personAuthResType {
+ code?: number;
+ message?: string;
+ result?: AuthResponse;
+}
+
export type operationButtonInfo = {
// 按钮名称
name: string;
@@ -2167,3 +2186,37 @@ export type operationButtonInfo = {
// 绑定场景
scene?: string;
};
+
+interface AuthResponse {
+ responseCode?: string;
+ responseMessage?: string;
+ verification?: boolean;
+}
+export interface componyAuthReqType {
+ organizationName: string;
+ orgIdentificationType: string;
+ orgIdentificationNumber: string;
+ name: string;
+ identificationType: string;
+ identificationNumber: string;
+ remark?: string;
+}
+
+export interface componyAuthResType {
+ code?: number;
+ message?: string;
+ result?: AuthResponse;
+}
+export interface personAuthReqType {
+ identificationType?: string;
+ identificationNumber: string;
+ name: string;
+ phoneNumber: string;
+ remark?: string;
+}
+
+export interface personAuthResType {
+ code?: number;
+ message?: string;
+ result?: AuthResponse;
+}
\ No newline at end of file
diff --git a/src/ts/core/target/base/team.ts b/src/ts/core/target/base/team.ts
index 01c3c47f27f63b3296e3814dcadc7111a30e2545..73559a5d28a4226cb2138e2a76f8c8b32b3cb82e 100644
--- a/src/ts/core/target/base/team.ts
+++ b/src/ts/core/target/base/team.ts
@@ -356,4 +356,4 @@ export abstract class Team extends Entity implements ITeam {
});
return res.data || { offset: offset, limit: 2000, result: [] };
}
-}
+}
\ No newline at end of file
diff --git a/typings/typing.d.ts b/typings/typing.d.ts
index 68a1561066275a861ed3c79c7f91d35131b960fd..4476e320f6aa49074852927c3827599420f75455 100644
--- a/typings/typing.d.ts
+++ b/typings/typing.d.ts
@@ -4,3 +4,7 @@ declare module 'less-vars-to-js';
declare module 'vite-plugin-style-import';
declare module 'pako';
declare module 'react-office-viewer';
+
+interface Window {
+ _GovAuthentication: any; // 浙里办人脸认证
+}
diff --git a/vite.config.ts b/vite.config.ts
index 5ccb7dbb14e4507ba84ddd218d98dc49304a9493..7463693c3f6c6ab14abc32ad0e24b139f89c36f6 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -38,7 +38,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
// 是否主动唤醒浏览器
open: false,
// 占用端口 开发环境启动的端口
- port: 8080,
+ port: 8081,
// 是否使用https请求
// https: true,
// 扩展访问端口
@@ -53,6 +53,11 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
changeOrigin: true, // 是否允许跨域
ws: true,
},
+ '/ZLB': {
+ target: 'https://asset.orginone.cn', // 后台接口
+ changeOrigin: true, // 是否允许跨域
+ ws: true,
+ },
},
},
build: {
@@ -98,7 +103,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
'html2canvas',
'@wangeditor/editor',
'@wangeditor/editor-for-react',
- ],
+ ],
'xlsx-vendor': ['xlsx'],
'play-vendor': ['jol-player'],
'dev-vendor': ['devextreme-react'],