index.vue 7.62 KB
<script setup lang="ts">
import { Button, Checkbox, Divider, Form, FormItem, InputPassword } from 'ant-design-vue'
import { computed, onMounted, reactive, ref, toRaw, unref } from 'vue'
import { useNodeData } from '../../hook/useNodeData'
import type { ConfigComponentProps } from '../../types'
import { useSavePageContent } from '../../hook/useSavePageContent'
import { ControlComponentEnum } from '../../packages/Control'
import { DataSourceForm } from './components/DataSourceForm'
import { DataEffects } from './components/DataEffects'
import { DataEvents } from './components/DataEvents'
import { createPublicFormContext } from './usePublicFormContext'
import { getInitStatusSettingDefaultValue } from './components/DataEffects/StatusSetting'
import type { ActTypeEnum, EventTypeEnum } from '@/enums/datasource'
import { useMessage } from '@/hooks/web/useMessage'
import type { NodeDataActJsonType, NodeDataEventJsonType, OperationPasswordDataType } from '@/api/node/model'
import { PackageCategoryEnum } from '@/core/Library/enum'
import { useContentDataStoreWithOut } from '@/store/modules/contentData'
import { BasicHelp } from '@/components/Basic'

const props = defineProps<ConfigComponentProps>()

const contentDataStore = useContentDataStoreWithOut()

const loading = ref(false)

const dataSourceElRef = ref<Nullable<InstanceType<typeof DataSourceForm>>>()

const dataEventsElRef = ref<InstanceType<typeof DataEvents>>()

const dataActElRef = ref<InstanceType<typeof DataEffects>>()

const operationPassword = reactive<OperationPasswordDataType>({
  checked: false,
  value: '',
  label: '操作密码',
  enable: true,
})

const nodeDataActinType = useNodeData({ cell: props.cell!, immediate: false })

const { getNodeData, getNodeAllData, saveNodeAllData, getCellInfo } = nodeDataActinType
const getFormSetting = computed(() => {
  return props.config?.presetOption?.publicFormSetting
})

const getComponentKey = computed(() => {
  return props.config?.key
})

const getEventJson = (): NodeDataEventJsonType => {
  const { eventJson } = toRaw(unref(getNodeData)) || {}

  if (!eventJson) return {} as any

  const status = unref(dataEventsElRef)?.getFieldsValue() as Record<EventTypeEnum, boolean>

  if (!status) return {} as any

  Object.keys(status).forEach((key) => {
    if (eventJson[key as EventTypeEnum])
      eventJson[key as EventTypeEnum]!.enable = status[key as EventTypeEnum]
  })

  return eventJson
}

const getActJson = (): NodeDataActJsonType => {
  const { actJson } = toRaw(unref(getNodeData)) || {}

  if (!actJson) return {} as NodeDataActJsonType

  if (unref(getCellInfo).componentKey === ControlComponentEnum.SWITCH && !actJson.STATUS_SETTING) {
    actJson.STATUS_SETTING = {
      enable: true,
      rangeList: getInitStatusSettingDefaultValue(),
    }
  }

  const status = unref(dataActElRef)?.getFieldsValue() as Record<ActTypeEnum, boolean>

  if (!status) return {} as NodeDataActJsonType

  Object.keys(status).forEach((key) => {
    if (actJson[key as ActTypeEnum])
      actJson[key as ActTypeEnum].enable = status[key as ActTypeEnum]
  })

  return actJson
}

const { createMessage } = useMessage()

const validatePassword = () => {
  return operationPassword.value ? Promise.resolve(operationPassword) : Promise.reject(new Error('请输入操作密码'))
}

const getSetPasswordStatus = computed(() => {
  const data = unref(getNodeData)?.eventJson?.SINGLE
  return !data
})

const { savePageContent } = useSavePageContent()
const handleSave = async () => {
  loading.value = true
  try {
    const eventJson = getEventJson()
    const actJson = getActJson()
    await unref(dataSourceElRef)?.validate()
    const value = unref(dataSourceElRef)?.getFieldsValue()
    let dataSourceJson = value
    if (operationPassword.checked)
      await validatePassword()
    if (contentDataStore.getIsTemplate)// 判断组态是不是模板
      dataSourceJson = { ...value, deviceProfileId: value?.deviceProfileTemplateId, deviceId: null, deviceName: null }
    await saveNodeAllData({ dataSourceJson, eventJson: { ...eventJson, OPERATION_PASSWORD: unref(getCellInfo).category === PackageCategoryEnum.CONTROL ? operationPassword : undefined }, actJson })
    createMessage.success('操作成功')
    savePageContent()
  }
  finally {
    loading.value = false
  }
}

const dataSourceChange = ref(false)
const handleDataSourceChange = () => {
  dataSourceChange.value = true
}

const handleBeforeOpenEventOrActModal = async () => {
  if (unref(dataSourceChange)) {
    await unref(dataSourceElRef)?.validate()
    const value = unref(dataSourceElRef)?.getFieldsValue()
    const { eventJson, actJson } = unref(getNodeData) || {}
    await saveNodeAllData({ eventJson, actJson, dataSourceJson: value })
  }
}

const handleSetFormValues = () => {
  unref(dataSourceElRef)?.setFieldsValue(unref(getNodeData)?.dataSourceJson)
  const { actJson, eventJson } = unref(getNodeData) || {}
  const { OPERATION_PASSWORD } = eventJson || {}
  if (OPERATION_PASSWORD)
    Object.assign(operationPassword, OPERATION_PASSWORD)

  const actStatus = Object.keys(actJson || {})
    .reduce((prev, next) => ({ ...prev, [next]: (actJson || {})[next as ActTypeEnum]?.enable }), {})

  const eventStatus = Object.keys(eventJson || {})
    .reduce((prev, next) => ({ ...prev, [next]: (eventJson || {})[next as EventTypeEnum]?.enable }), {})
  unref(dataActElRef)?.setFieldsValue(actStatus)
  unref(dataEventsElRef)?.setFieldsValue(eventStatus)
}

const getValidateStatus = (value: string | number) => {
  if (!operationPassword.checked) return ''
  return value ? '' : 'error'
}

onMounted(async () => {
  await getNodeAllData()
  handleSetFormValues()
})
createPublicFormContext(nodeDataActinType)
</script>

<template>
  <main class="form-container px-4">
    <div v-if="getFormSetting && getFormSetting.dataSourceSetting">
      <Divider orientation="left">
        数据源
      </Divider>
      <DataSourceForm
        ref="dataSourceElRef" :component-key="getComponentKey"
        @field-value-change="handleDataSourceChange"
      />
    </div>
    <div v-if="getFormSetting && getFormSetting.eventSetting !== false">
      <Divider orientation="left">
        数据交互
      </Divider>
      <DataEvents ref="dataEventsElRef" :before-click="handleBeforeOpenEventOrActModal" :form-setting="getFormSetting" />
      <div
        v-if="getCellInfo.category === PackageCategoryEnum.CONTROL" class="flex flex-col justify-center passwordInput"
        :class="getFormSetting?.actSetting === false && 'mb-4'"
      >
        <Checkbox v-model:checked="operationPassword.checked" :disabled="getSetPasswordStatus">
          <div class="flex">
            {{ operationPassword.label }}
            <BasicHelp class="ml-1" text="操作密码: 需完成单击事件交互。" />
          </div>
        </Checkbox>
        <Form>
          <FormItem :validate-status="getValidateStatus(operationPassword.value!)">
            <InputPassword
              v-model:value="operationPassword.value" class="mt-1" :disabled="!operationPassword.checked"
              placeholder="请输入操作密码"
            />
          </FormItem>
        </Form>
      </div>
    </div>
    <div v-if="getFormSetting && getFormSetting.actSetting !== false">
      <Divider orientation="left">
        数据动效
      </Divider>
      <DataEffects ref="dataActElRef" :before-click="handleBeforeOpenEventOrActModal" :form-setting="getFormSetting" />
    </div>
    <Button class="w-full" type="primary" :loading="loading" @click="handleSave">
      保存
    </Button>
  </main>
</template>

<style lang="less" scoped>
.form-container {
  @apply text-sm;

  :deep(.ant-divider) {
    @apply text-sm;
  }
}

.passwordInput {
  :deep(.ant-form-item) {
    margin: 0 !important
  }
}
</style>