lodash#difference JavaScript Examples

The following examples show how to use lodash#difference. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js    From flatris-LAB_V1 with MIT License 6 votes vote down vote up
componentDidUpdate({ games: prevGames }) {
    const { games } = this.props;
    const ids = Object.keys(games);
    const prevIds = Object.keys(prevGames);

    if (games !== prevGames) {
      const justAdded = difference(ids, prevIds);
      const justRemoved = difference(prevIds, ids);

      const { gamesCopy, added } = this.state;
      const newState = {
        // Keep current games as well as just-removed games in state
        gamesCopy: { ...gamesCopy, ...games },
        added: [...added, ...justAdded]
      };

      this.setState(newState, () => {
        justAdded.forEach(this.scheduleClearAdded);
        justRemoved.forEach(this.scheduleClearRemoved);
      });
    }

    ids
      .filter(gameId => games[gameId] !== prevGames[gameId])
      .forEach(this.bumpInactiveTimeout);
  }
Example #2
Source File: MappingProfilesFormContainer.js    From ui-data-export with Apache License 2.0 6 votes vote down vote up
isValidRecordTypesMatching = (selectedTransformations = [], selectedRecordTypes = []) => {
  const isOnlySrsSelected = selectedRecordTypes.length === 1 && selectedRecordTypes[0] === FOLIO_RECORD_TYPES.SRS.type;

  if (isEmpty(selectedTransformations) && !isOnlySrsSelected) {
    return false;
  }

  const recordTypesInTransformations = uniq(selectedTransformations.map(({ recordType }) => recordType));

  const validatedRecords = selectedRecordTypes.filter(recordType => recordType !== FOLIO_RECORD_TYPES.SRS.type);

  return isEmpty(difference(recordTypesInTransformations, validatedRecords))
    && isEmpty(difference(validatedRecords, recordTypesInTransformations));
}
Example #3
Source File: taskFilters.js    From os-league-tools with MIT License 6 votes vote down vote up
function skillFilter(record, filterState, { hiscoresState }) {
    const taskSkills = record.skillReqs.map(req => req.skill);

    // Check if required skills are included in filter
    const includeNoReq = filterState.showNoRequirements;
    const hasValidSkills = difference(taskSkills, filterState.skills).length === 0;
    if (!hasValidSkills || (!includeNoReq && taskSkills.length === 0)) {
        return false;
    }

    // Check if level requirements should be ignored
    if (!hiscoresState || hiscoresState.loading || hiscoresState.error || filterState.showUnmetRequirements) {
        return true;
    }

    // Check if level requirements are met
    let meetsRequirements = true;
    record.skillReqs.forEach(skillReq => {
        const hiscores = hiscoresState.skills[skillReq.skill.toLowerCase()];
        const levelBoost = filterState.isUnchainedTalent && STATS[skillReq.skill]?.unchainedTalentEligible ? 8 : 0;
        const level = (hiscores?.level || 1) + levelBoost;
        meetsRequirements = meetsRequirements && level >= skillReq.level;
    });
    return meetsRequirements;
}
Example #4
Source File: socket.js    From flatris-LAB_V1 with MIT License 4 votes vote down vote up
export function attachSocket(server: net$Server) {
  const io = socketIo(server);

  io.on('connect', socket => {
    console.log('New socket connection');

    socket.on('subscribe', (roomId: RoomId) => {
      console.log(`[SOCKET] subscribe ${roomId}`);

      const prevRooms = Object.keys(omit(socket.rooms, socket.id));
      const roomsToJoin = difference([roomId], prevRooms);
      const roomsToLeave = difference(prevRooms, [roomId]);

      socket.join(roomsToJoin);
      roomsToLeave.forEach(gameId => socket.leave(gameId));
    });

    socket.on('game-keep-alive', (gameId: GameId) => {
      console.log(`[SOCKET] game-keep-alive ${gameId}`);

      if (!games[gameId]) {
        // NOTE: This message can flood the logs if client gets stuck
        // console.warn(`Received keep-alive for missing game ${gameId}`);

        // Notify client to leave expired game page
        socket.emit('game-removed', gameId);
      } else {
        // As long as games are open they are marked as active
        bumpActiveGame(gameId);

        socket.to('global').broadcast.emit('game-keep-alive', gameId);
      }
    });

    socket.on('game-action', (action: GameAction) => {
      // console.log('[SOCKET] game-action', action);

      const { gameId } = action.payload;
      const prevGame = games[gameId];
      if (!prevGame) {
        // NOTE: This message can flood the logs if client gets stuck
        // console.warn(`Received keep-alive for missing game ${gameId}`);

        // Notify client to leave expired game page
        socket.emit('game-removed', gameId);
      } else {
        try {
          const game = gameReducer(prevGame, action);
          games[gameId] = game;

          // Only save game action after game reducer was run successfully
          saveGameAction(action);

          // As long as games receive actions they are marked as active
          bumpActiveGame(gameId);

          socket
            .to(gameId)
            // TODO: Filter which actions get sent to `global` if volume is high
            .to('global')
            .broadcast.emit('game-action', action);

          countTurns(game, prevGame);
          countControlAction(action);
          countLines(action, game, prevGame);
          countGameTime(action);
        } catch (err) {
          const player = getPlayer(prevGame, action.payload.userId);
          const syncId = `${prevGame.id}-${player.lastActionId}`;

          // Prevent syncing more than once for the same player. Context: After
          // going offline and back online, often many messages are queued and
          // sent all at once. In the past this would flood the logs and
          // trigger hundreds of game-sync events at once.
          if (!gameSync[syncId]) {
            gameSync[syncId] = true;

            rollbar.error(err, { action });

            // Sync client state with server state. This happens when one client
            // goes offline for a while and then goes back online. Upon
            // reconnecting the client will have a going-back-in-time experience,
            // as all their actions that were performed during the offline period
            // will be canceled
            // NOTE: This is not enough if client doesn't also join game room
            // again upon reconnect
            socket.emit('game-sync', prevGame);
          }
        }
      }
    });
  });

  onStatsChange(stats => {
    io.to('global').emit('stats', stats);
  });
}
Example #5
Source File: index.js    From datapass with GNU Affero General Public License v3.0 4 votes vote down vote up
DonneesSection = ({
  DonneesDescription,
  availableScopes = [],
  AvailableScopesDescription,
  accessModes,
  enableFileSubmissionForScopeSelection = false,
}) => {
  const {
    disabled,
    onChange,
    enrollment: {
      scopes = {},
      data_recipients = '',
      data_retention_period = '',
      data_retention_comment = '',
      additional_content = {},
      documents = [],
      documents_attributes = [],
    },
  } = useContext(FormContext);

  useEffect(() => {
    if (!isEmpty(availableScopes) && isEmpty(scopes)) {
      onChange({
        target: {
          name: 'scopes',
          value: zipObject(
            availableScopes.map(({ value }) => value),
            availableScopes.map(
              ({ required, checkedByDefault }) =>
                !!required || !!checkedByDefault
            )
          ),
        },
      });
    }
  });

  const groupTitleScopesGroup = groupBy(
    availableScopes,
    (e) => e.groupTitle || 'default'
  );

  // {'a': true, 'b': false, 'c': true} becomes ['a', 'c']
  const scopesAsArray = chain(scopes)
    .omitBy((e) => !e)
    .keys()
    .value();
  const availableScopesAsArray = availableScopes.map(({ value }) => value);
  const outdatedScopes = difference(scopesAsArray, availableScopesAsArray);

  const [isFileInputExpanded, setFileInputExpanded] = useState(
    enableFileSubmissionForScopeSelection &&
      !isEmpty(
        documents.filter(
          ({ type }) => type === 'Document::ExpressionBesoinSpecifique'
        )
      )
  );

  useEffect(() => {
    const hasDocument = !isEmpty(
      documents.filter(
        ({ type }) => type === 'Document::ExpressionBesoinSpecifique'
      )
    );
    if (
      enableFileSubmissionForScopeSelection &&
      !isFileInputExpanded &&
      hasDocument
    ) {
      setFileInputExpanded(true);
    }
  }, [enableFileSubmissionForScopeSelection, isFileInputExpanded, documents]);

  return (
    <ScrollablePanel scrollableId={SECTION_ID}>
      <h2>Les données nécessaires</h2>
      {DonneesDescription && (
        <ExpandableQuote title="Comment choisir les données ?">
          <DonneesDescription />
        </ExpandableQuote>
      )}
      {AvailableScopesDescription && <AvailableScopesDescription />}
      {!isEmpty(availableScopes) && (
        <>
          <h3>À quelles données souhaitez-vous avoir accès ?</h3>
          {Object.keys(groupTitleScopesGroup).map((group) => (
            <Scopes
              key={group}
              title={group === 'default' ? null : group}
              scopes={groupTitleScopesGroup[group]}
              selectedScopes={scopes}
              disabledApplication={disabled}
              handleChange={onChange}
            />
          ))}
          {disabled && !isEmpty(outdatedScopes) && (
            <Scopes
              title="Les données suivantes ont été sélectionnées mais ne sont plus disponibles :"
              scopes={outdatedScopes.map((value) => ({ value, label: value }))}
              selectedScopes={zipObject(
                outdatedScopes,
                Array(outdatedScopes.length).fill(true)
              )}
              disabledApplication
              handleChange={() => null}
            />
          )}
        </>
      )}
      {enableFileSubmissionForScopeSelection && (
        <>
          <ExpandableQuote title="J’ai une expression de besoin spécifique ?">
            <p>
              Les partenaires ayant convenu avec la DGFiP un périmètre de
              données particulier peuvent rattacher leur expression de besoin
              listant l’ensemble des données strictement nécessaires à leur cas
              d’usage. Si vous n'avez pas encore contacté la DGFiP, vous pouvez
              les joindre à l'adresse{' '}
              <Link
                inline
                href="mailto:[email protected]?subject=Expression%20de%20besoin%20spécifique"
              >
                [email protected]
              </Link>
            </p>
            <CheckboxInput
              label="J’ai une expression de besoin spécifique"
              value={isFileInputExpanded}
              onChange={() => setFileInputExpanded(!isFileInputExpanded)}
              disabled={disabled}
            />
          </ExpandableQuote>
          {isFileInputExpanded && (
            <>
              <FileInput
                label="Joindre l’expression de besoin"
                meta={
                  'Attention : seule l’expression de besoin en données ayant déjà été partagée avec la DGFiP peut être rattachée à votre habilitation.'
                }
                mimeTypes="*"
                disabled={disabled}
                uploadedDocuments={documents}
                documentsToUpload={documents_attributes}
                documentType={'Document::ExpressionBesoinSpecifique'}
                onChange={onChange}
              />
            </>
          )}
        </>
      )}
      {!isEmpty(accessModes) && (
        <>
          <h3>Comment souhaitez-vous y accéder ?</h3>
          {accessModes.map(({ id, label }) => (
            <CheckboxInput
              key={id}
              label={label}
              name={`additional_content.${id}`}
              value={additional_content[id] || false}
              disabled={disabled}
              onChange={onChange}
            />
          ))}
        </>
      )}
      <h3>Comment seront traitées ces données personnelles ?</h3>
      <TextInput
        label="Destinataires des données"
        placeholder={
          '« agents instructeurs des demandes d’aides », « usagers des ' +
          'services publics de la ville », etc.'
        }
        meta={
          <Link
            inline
            newTab
            href="https://www.cnil.fr/fr/definition/destinataire"
            aria-label="Voir la définition CNIL du destinataire des données"
          >
            Plus d’infos
          </Link>
        }
        name="data_recipients"
        value={data_recipients}
        disabled={disabled}
        onChange={onChange}
        required
      />
      <NumberInput
        label="Durée de conservation des données en mois"
        meta={
          <Link
            inline
            newTab
            href="https://www.cnil.fr/fr/les-durees-de-conservation-des-donnees"
            aria-label="Voir l’explication CNIL sur les durées de conservation des données"
          >
            Plus d’infos
          </Link>
        }
        name="data_retention_period"
        value={data_retention_period}
        disabled={disabled}
        onChange={onChange}
        required
      />
      {data_retention_period > 36 && (
        <>
          <Alert type="warning" title="Attention">
            Cette durée excède la durée communément constatée (36 mois).
          </Alert>
          <TextInput
            label="Veuillez justifier cette durée dans le champ ci-après :"
            name="data_retention_comment"
            value={data_retention_comment}
            disabled={disabled}
            onChange={onChange}
          />
        </>
      )}
    </ScrollablePanel>
  );
}
Example #6
Source File: EditForm.js    From hzero-front with Apache License 2.0 4 votes vote down vote up
EditFrom = ({
  form,
  initData,
  dimensionTypes,
  match,
  onRecordAdd,
  onRecordEdit,
  onRecordDelete,
  onTableChange,
  dimensionConfigsDataSource,
  dimensionConfigsPagination,
  dimensionAllowChange,
  interactedRef,
  isCreate,
  deleteDimensionConfigsLoading = false,
}) => {
  const rateLimitDimension = form.getFieldValue('rateLimitDimension') || [];
  React.useImperativeHandle(
    interactedRef,
    () => ({
      getValidateData() {
        return new Promise((resolve, reject) => {
          form.validateFields((err, values) => {
            if (err) {
              reject(err);
            } else {
              resolve(values);
            }
          });
        });
      },
    }),
    [interactedRef, form]
  );
  /**
   * 维度规则表格列
   * @type {unknown}
   */
  const columns = React.useMemo(() => {
    if (isCreate) {
      return [];
    } else {
      return rateLimitDimension
        .map(dimensionValue => {
          const dimensionItem = dimensionTypes.find(item => item.value === dimensionValue);
          return (
            dimensionItem && {
              // 仅做显示
              title: dimensionItem.meaning,
              dataIndex: getDimensionMeaningDataIndex(dimensionItem.value),
            }
          );
        })
        .filter(Boolean)
        .concat([
          // 操作列
          {
            title: intl.get('hzero.common.button.action').d('操作'),
            key: 'operator',
            fixed: 'right',
            width: 120,
            render: (_, record) => {
              const actions = [];
              actions.push({
                ele: (
                  <ButtonPermission
                    type="text"
                    permissionList={[
                      {
                        code: `${match.path}.button.edit`,
                        type: 'button',
                        meaning: '限流规则-维度-编辑限流规则(表格)',
                      },
                    ]}
                    key="action-edit"
                    onClick={() => {
                      onRecordEdit(form.getFieldValue('rateLimitDimension') || [], record);
                    }}
                  >
                    {intl.get('hzero.common.button.edit').d('编辑')}
                  </ButtonPermission>
                ),
                len: 2,
                title: intl.get('hzero.common.button.edit').d('编辑'),
              });
              actions.push({
                ele: (
                  <Popconfirm
                    title={intl.get('hzero.common.message.confirm.delete').d('是否删除此条记录?')}
                    key="action-edit"
                    onConfirm={() => {
                      onRecordDelete(record);
                    }}
                  >
                    <ButtonPermission
                      type="text"
                      permissionList={[
                        {
                          code: `${match.path}.button.delete`,
                          type: 'button',
                          meaning: '限流规则-维度-删除限流规则(表格)',
                        },
                      ]}
                    >
                      {intl.get('hzero.common.button.delete').d('删除')}
                    </ButtonPermission>
                  </Popconfirm>
                ),
                len: 2,
                title: intl.get('hzero.common.button.delete').d('删除'),
              });
              return operatorRender(actions);
            },
          },
        ]);
    }
  }, [dimensionTypes, isCreate, [...rateLimitDimension].sort().join(',')]);
  /**
   * 新增按钮点击
   * @type {Function}
   */
  const handleAdd = React.useCallback(() => {
    onRecordAdd(form.getFieldValue('rateLimitDimension'));
  }, [onRecordAdd, form]);

  // 如果可以修改维度, 那么修改维度后就不能修改维度规则
  const dimensionAllowChangeDuringUpdate =
    !dimensionAllowChange ||
    (dimensionAllowChange &&
      // dimensionAllowChange true -> 维度有值
      // 当前没有更新过 url/维度值
      difference(form.getFieldValue('rateLimitDimension'), initData.rateLimitDimension).length ===
        0 &&
      // 不存在 url 模板
      ((!form.getFieldValue('data-extra__rateLimitDimension_url') &&
        !initData['data-extra__rateLimitDimension_url']) ||
        // 存在url模板
        initData['data-extra__rateLimitDimension_url'] ===
          form.getFieldValue('data-extra__rateLimitDimension_url')));

  return (
    <Form>
      <Row type="flex">
        <Col {...FORM_COL_2_LAYOUT}>
          <Form.Item
            {...MODAL_FORM_ITEM_LAYOUT}
            label={intl.get(`hadm.zuulRateLimit.model.zuulRateLimit.path`).d('服务路由')}
          >
            {form.getFieldDecorator('serviceRouteId', {
              initialValue: initData.serviceRouteId,
              rules: [
                {
                  required: true,
                  message: intl.get('hzero.common.validation.notNull', {
                    name: intl.get(`hadm.zuulRateLimit.model.zuulRateLimit.path`).d('服务路由'),
                  }),
                },
              ],
            })(<Lov code="HADM.SERVICE_ROUTE" textValue={initData.path} />)}
          </Form.Item>
        </Col>
        <Col {...FORM_COL_2_LAYOUT}>
          <Form.Item
            {...MODAL_FORM_ITEM_LAYOUT}
            label={intl
              .get(`hadm.zuulRateLimit.model.zuulRateLimit.replenishRate`)
              .d('每秒流量限制值')}
          >
            {form.getFieldDecorator('replenishRate', {
              rules: [
                {
                  required: true,
                  message: intl.get('hzero.common.validation.notNull', {
                    name: intl
                      .get(`hadm.zuulRateLimit.model.zuulRateLimit.replenishRate`)
                      .d('每秒流量限制值'),
                  }),
                },
              ],
              initialValue: initData.replenishRate,
            })(<InputNumber min={1} />)}
          </Form.Item>
        </Col>
        <Col {...FORM_COL_2_LAYOUT}>
          <Form.Item
            {...MODAL_FORM_ITEM_LAYOUT}
            label={intl
              .get('hadm.zuulRateLimit.model.zuulRateLimit.rateLimitDimension')
              .d('限流维度')}
          >
            {form.getFieldDecorator('rateLimitDimension', {
              initialValue: isCreate ? [] : initData.rateLimitDimension,
              rules: [
                {
                  type: 'array',
                  required: true,
                  message: intl.get('hzero.common.validation.notNull', {
                    name: intl
                      .get('hadm.zuulRateLimit.model.zuulRateLimit.rateLimitDimension')
                      .d('限流维度'),
                  }),
                },
              ],
            })(
              <Select allowClear disabled={!dimensionAllowChange} mode="multiple">
                {dimensionTypes.map(item => (
                  <Select.Option value={item.value} key={item.value}>
                    {item.meaning}
                  </Select.Option>
                ))}
              </Select>
            )}
          </Form.Item>
        </Col>
        <Col {...FORM_COL_2_LAYOUT}>
          <Form.Item
            {...MODAL_FORM_ITEM_LAYOUT}
            label={intl
              .get(`hadm.zuulRateLimit.model.zuulRateLimit.burstCapacity`)
              .d('突发流量限制值')}
          >
            {form.getFieldDecorator('burstCapacity', {
              initialValue: initData.burstCapacity,
            })(<InputNumber min={1} />)}
          </Form.Item>
        </Col>
        <Col {...FORM_COL_2_LAYOUT}>
          <Form.Item
            {...MODAL_FORM_ITEM_LAYOUT}
            label={intl.get(`hzero.common.status.enable`).d('启用')}
          >
            {form.getFieldDecorator('enabledFlag', {
              initialValue: initData.enabledFlag === 0 ? 0 : 1,
            })(<Switch />)}
          </Form.Item>
        </Col>
      </Row>
      <Row>
        {rateLimitDimension.includes('url') && (
          <Col {...FORM_COL_2_LAYOUT}>
            <Form.Item
              {...MODAL_FORM_ITEM_LAYOUT}
              label={
                <span>
                  {intl.get(`hadm.zuulRateLimit.model.zuulRateLimit.dataExtraUrl`).d('URL维度值')}
                  <Tooltip
                    title={intl
                      .get('hadm.zuulRateLimit.view.message.url')
                      .d(
                        'URL特殊字符需使用encode后的值,变量使用{数字}占位, 且不能包含空白和特殊字符?(){}&= 示例: /hiam/v1/{1}/{2}?tenantId={3}&roleId={4}'
                      )}
                  >
                    <Icon type="question-circle-o" />
                  </Tooltip>
                </span>
              }
            >
              {form.getFieldDecorator('data-extra__rateLimitDimension_url', {
                initialValue: initData['data-extra__rateLimitDimension_url'],
                rules: [
                  {
                    pattern: /^(([^?(){}&=\s]|(\{\d+\}))*)+(\?([^?(){}&=\s]|(\{\d+\}))*=([^?(){}&=\s]|(\{\d+\}))*(&([^?(){}&=\s]|(\{\d+\}))*=([^?(){}&=\s]|(\{\d+\}))*)*)?$/,
                    message: intl
                      .get('hadm.zuul.RateLimit.view.validation.dimension.url')
                      .d('URL必须符合规则'),
                  },
                ],
              })(<Input disabled={!dimensionAllowChange} />)}
            </Form.Item>
          </Col>
        )}
      </Row>
      <Row>
        <Col>
          <Form.Item
            label={intl.get('hadm.zuulRateLimit.model.zuulRateLimit.dimensionLine').d('限流规则')}
            labelCol={{ span: 3 }}
            wrapperCol={{ span: 21 }}
          >
            {!dimensionAllowChangeDuringUpdate ? (
              intl
                .get('hadm.zuulRateLimit.view.message.notLimitDuringCreate')
                .d('保存限流路由后再编辑限流规则')
            ) : (
              <ButtonPermission
                permissionList={[
                  {
                    code: `${match.path}.button.valueAdd`,
                    type: 'button',
                    meaning: '限流规则-维度-新增限流规则',
                  },
                ]}
                onClick={handleAdd}
                htmlType="button"
                disabled={(form.getFieldValue('rateLimitDimension') || []).length === 0}
              >
                {intl.get('hadm.zuulRateLimit.view.form.create').d('新增限流规则')}
              </ButtonPermission>
            )}
          </Form.Item>
        </Col>
      </Row>
      {dimensionAllowChangeDuringUpdate && (
        <Row type="flex">
          <Col span={3} />
          <Col span={21}>
            <Table
              bordered
              loading={deleteDimensionConfigsLoading}
              rowKey="rateLimitDimId"
              dataSource={dimensionConfigsDataSource}
              pagination={dimensionConfigsPagination}
              onChange={onTableChange}
              columns={columns}
            />
          </Col>
        </Row>
      )}
    </Form>
  );
}
Example #7
Source File: apiManagementGroupDS.js    From hzero-front with Apache License 2.0 4 votes vote down vote up
function tableDS(formRecord) {
  return {
    dataKey: 'content',
    cacheSelection: true,
    fields: [
      {
        name: 'id',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.id').d('权限id'),
        unique: true,
      },
      {
        name: 'code',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.code').d('权限编码'),
      },
      {
        name: 'path',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.path').d('路径'),
      },
      {
        name: 'method',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.method').d('请求方式'),
      },
      {
        name: 'methodMeaning',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.methodMeaning').d('请求方式'),
      },
      {
        name: 'fdLevel',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.fieldLevel').d('权限层级'),
      },
      {
        name: 'levelMeaning',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.levelMeaning').d('权限层级'),
      },
      {
        name: 'description',
        type: 'intl',
        label: intl.get('hiam.apiManagement.model.apiManagement.description').d('描述'),
        maxLength: 1024,
      },
      {
        name: 'action',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.action').d('方法名'),
      },
      {
        name: 'resource',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.resource').d('资源类型'),
      },
      {
        name: 'serviceName',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.serviceName').d('服务名称'),
      },
      {
        name: 'publicAccess',
        type: 'number',
        label: intl.get('hiam.apiManagement.model.apiManagement.publicAccess').d('是否公开接口'),
      },
      {
        name: 'loginAccess',
        type: 'number',
        label: intl.get('hiam.apiManagement.model.apiManagement.loginAccess').d('是否登录可访问'),
      },
      {
        name: 'within',
        type: 'number',
        label: intl.get('hiam.apiManagement.model.apiManagement.within').d('是否内部接口'),
      },
      {
        name: 'signAccess',
        type: 'number',
        label: intl.get('hiam.apiManagement.model.apiManagement.signAccess').d('是否签名接口'),
      },
      {
        name: 'objectVersionNumber',
        type: 'number',
        label: intl.get('hiam.apiManagement.model.apiManagement.objectVersionNumber').d('版本'),
      },
      {
        name: 'tag',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.tag').d('标签'),
      },
      {
        name: 'pageTag',
        type: 'string',
        label: intl.get('hiam.apiManagement.model.apiManagement.pageTag').d('API标签'),
        bind: 'apiTags.PAGE',
      },
      // {
      //   name: 'backgroundTag',
      //   type: 'string',
      //   label: intl.get('hiam.apiManagement.model.apiManagement.backgroundTag').d('后端API标识'),
      //   bind: 'apiTags.BACKEND',
      // },
    ],
    events: {
      query: ({ dataSet }) => {
        dataSet.unSelectAll();
        dataSet.clearCachedSelected();
      },
      update: ({ record, dataSet, value, oldValue }) => {
        // if (!isEmpty(dataSet.frontLabels)) {
        if (isArray(value) || isArray(oldValue)) {
          if ((value || []).sort().toString() !== (oldValue || []).sort().toString()) {
            if (isEmpty(value)) {
              const PAGE = uniq(
                oldValue.filter((item) => {
                  return (dataSet.frontLabels || []).includes(item);
                })
              );
              record.set('apiTags', { PAGE, BACKEND: [] });
            } else if ((dataSet.frontLabels || []).includes(difference(oldValue, value)[0])) {
              record.set('apiTags', { PAGE: oldValue, BACKEND: [] });
            } else {
              record.set('apiTags', { PAGE: value.sort(), BACKEND: [] });
            }
          }
        } else if (isArray(value) && !isArray(oldValue)) {
          record.set('apiTags', { PAGE: value.sort(), BACKEND: [] });
        }
        // }
      },
    },
    transport: {
      read: (config) => {
        const { params } = config;
        const url = isTenantRoleLevel()
          ? `${HZERO_IAM}/hzero/v1/${organizationId}/permissions`
          : `${HZERO_IAM}/hzero/v1/permissions`;
        let data = {};
        if (formRecord.toData()[0]) {
          const {
            code = '',
            path = '',
            serviceName = '',
            fdLevel = '',
            method = '',
            labels = '',
            publicAccess = undefined,
            loginAccess = undefined,
            within = undefined,
            signAccess = undefined,
          } = formRecord.toData()[0];
          const obj = {
            publicAccess:
              isUndefined(publicAccess) || publicAccess === null ? undefined : !!publicAccess,
            loginAccess:
              isUndefined(loginAccess) || loginAccess === null ? undefined : !!loginAccess,
            within: isUndefined(within) || within === null ? undefined : !!within,
            signAccess: isUndefined(signAccess) || signAccess === null ? undefined : !!signAccess,
          };
          data = filterNullValueObject({
            code,
            path,
            serviceName,
            fdLevel,
            method,
            labels,
            ...obj,
          });
        }
        return {
          data,
          params,
          url,
          method: 'GET',
        };
      },
      update: (config) => {
        const url = isTenantRoleLevel()
          ? `${HZERO_IAM}/hzero/v1/${organizationId}/permissions/update`
          : `${HZERO_IAM}/hzero/v1/permissions/update`;
        const { data = [], dataSet } = config;
        const { _status, apiTags, pageTag, ...other } = data[0];
        const tags = (dataSet.labelList || [])
          .filter((item) => {
            return (data[0].apiTags.PAGE || []).includes(item.name);
          })
          .map((item) => ({ id: item.id, _token: item._token }));
        return {
          data: {
            ...other,
            labels: tags,
          },
          url,
          method: 'PUT',
        };
      },
      destroy: (config) => {
        const url = isTenantRoleLevel()
          ? `${HZERO_IAM}/hzero/v1/${organizationId}/permissions`
          : `${HZERO_IAM}/hzero/v1/permissions`;
        const { params = {}, data = [] } = config;
        return {
          data,
          params,
          url,
          method: 'DELETE',
        };
      },
    },
  };
}