245 lines
6.8 KiB
Vue
245 lines
6.8 KiB
Vue
<template>
|
||
<ElDialog
|
||
v-model="visible"
|
||
:title="isEdit ? '编辑企微应用' : '新增企微应用'"
|
||
width="50%"
|
||
destroy-on-close
|
||
@closed="resetForm"
|
||
>
|
||
<div class="dialog-description">应用凭据由平台管理员维护,保存后可在应用列表测试连接。</div>
|
||
|
||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="130px" class="application-form">
|
||
<ElRow :gutter="24">
|
||
<ElCol :xs="24" :sm="12">
|
||
<ElFormItem label="企业 ID" prop="corp_id">
|
||
<ElInput v-model="form.corp_id" placeholder="请输入企业微信 CorpID" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :xs="24" :sm="12">
|
||
<ElFormItem label="AgentID" prop="agent_id">
|
||
<ElInputNumber
|
||
v-model="form.agent_id"
|
||
:min="1"
|
||
controls-position="right"
|
||
class="full-width"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :xs="24" :sm="12">
|
||
<ElFormItem label="应用名称" prop="name">
|
||
<ElInput v-model="form.name" placeholder="请输入应用名称" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :xs="24" :sm="12">
|
||
<ElFormItem label="Secret" prop="secret">
|
||
<ElInput
|
||
v-model="form.secret"
|
||
type="password"
|
||
show-password
|
||
placeholder="请输入应用 Secret"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
|
||
<ElDivider content-position="left">回调配置</ElDivider>
|
||
<ElRow :gutter="24">
|
||
<ElCol :span="24">
|
||
<ElFormItem label="回调 Token" prop="callback_token">
|
||
<ElInput
|
||
v-model="form.callback_token"
|
||
type="textarea"
|
||
:rows="3"
|
||
resize="vertical"
|
||
placeholder="请输入回调 Token"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="24">
|
||
<ElFormItem label="EncodingAESKey" prop="encoding_aes_key">
|
||
<ElInput
|
||
v-model="form.encoding_aes_key"
|
||
type="textarea"
|
||
:rows="3"
|
||
resize="vertical"
|
||
placeholder="请输入 43 位 EncodingAESKey"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
|
||
<ElFormItem label="启用状态">
|
||
<ElSwitch v-model="form.enabled" active-text="启用" inactive-text="禁用" />
|
||
</ElFormItem>
|
||
</ElForm>
|
||
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<ElButton @click="visible = false">取消</ElButton>
|
||
<ElButton
|
||
v-if="isEdit"
|
||
v-permission="JULY_PERMISSIONS.wecom.application"
|
||
:loading="testing"
|
||
@click="testApplication"
|
||
>
|
||
测试连接
|
||
</ElButton>
|
||
<ElButton
|
||
v-permission="JULY_PERMISSIONS.wecom.application"
|
||
type="primary"
|
||
:loading="saving"
|
||
@click="saveApplication"
|
||
>
|
||
保存应用
|
||
</ElButton>
|
||
</div>
|
||
</template>
|
||
</ElDialog>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, reactive, ref, watch } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import type { FormInstance, FormRules } from 'element-plus'
|
||
import { WecomService } from '@/api/modules'
|
||
import { JULY_PERMISSIONS } from '@/config/constants'
|
||
import type { WecomApplication } from '@/types/api'
|
||
|
||
defineOptions({ name: 'WecomApplicationFormDialog' })
|
||
|
||
const props = defineProps<{
|
||
modelValue: boolean
|
||
application: WecomApplication | null
|
||
}>()
|
||
|
||
const emit = defineEmits<{
|
||
(event: 'update:modelValue', value: boolean): void
|
||
(event: 'success'): void
|
||
}>()
|
||
|
||
const visible = computed({
|
||
get: () => props.modelValue,
|
||
set: (value: boolean) => emit('update:modelValue', value)
|
||
})
|
||
const isEdit = computed(() => Boolean(props.application?.id))
|
||
const formRef = ref<FormInstance>()
|
||
const saving = ref(false)
|
||
const testing = ref(false)
|
||
const form = reactive({
|
||
corp_id: '',
|
||
agent_id: 0,
|
||
name: '',
|
||
secret: '',
|
||
callback_token: '',
|
||
encoding_aes_key: '',
|
||
enabled: true
|
||
})
|
||
|
||
const rules = reactive<FormRules>({
|
||
corp_id: [{ required: true, message: '请输入企业 ID', trigger: 'blur' }],
|
||
agent_id: [{ required: true, message: '请输入 AgentID', trigger: 'change' }],
|
||
name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
|
||
secret: [{ required: true, message: '请输入 Secret', trigger: 'blur' }]
|
||
})
|
||
|
||
const fillForm = (application: WecomApplication | null) => {
|
||
Object.assign(
|
||
form,
|
||
application
|
||
? {
|
||
corp_id: application.corp_id,
|
||
agent_id: application.agent_id,
|
||
name: application.name,
|
||
secret: application.secret || '',
|
||
callback_token: application.callback_token || '',
|
||
encoding_aes_key: application.encoding_aes_key || '',
|
||
enabled: application.status === 1
|
||
}
|
||
: {
|
||
corp_id: '',
|
||
agent_id: 0,
|
||
name: '',
|
||
secret: '',
|
||
callback_token: '',
|
||
encoding_aes_key: '',
|
||
enabled: true
|
||
}
|
||
)
|
||
}
|
||
|
||
const resetForm = () => {
|
||
fillForm(null)
|
||
formRef.value?.clearValidate()
|
||
}
|
||
|
||
const saveApplication = async () => {
|
||
const valid = await formRef.value?.validate().catch(() => false)
|
||
if (!valid) return
|
||
|
||
saving.value = true
|
||
try {
|
||
const response = await WecomService.saveApplication({
|
||
corp_id: form.corp_id,
|
||
agent_id: form.agent_id,
|
||
name: form.name,
|
||
secret: form.secret,
|
||
callback_token: form.callback_token,
|
||
encoding_aes_key: form.encoding_aes_key,
|
||
status: form.enabled ? 1 : 0
|
||
})
|
||
if (response.code === 0) {
|
||
ElMessage.success('企微应用保存成功')
|
||
emit('success')
|
||
visible.value = false
|
||
}
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
const testApplication = async () => {
|
||
if (!props.application?.id) return
|
||
|
||
testing.value = true
|
||
try {
|
||
const response = await WecomService.testApplication(props.application.id)
|
||
if (response.code === 0) {
|
||
if (response.data.success) ElMessage.success('连接成功,已取得 access_token')
|
||
else ElMessage.warning('连接失败,请检查应用凭据')
|
||
}
|
||
} finally {
|
||
testing.value = false
|
||
}
|
||
}
|
||
|
||
watch(
|
||
() => [props.modelValue, props.application] as const,
|
||
([opened]) => {
|
||
if (opened) fillForm(props.application)
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.dialog-description {
|
||
margin-bottom: 20px;
|
||
color: var(--el-text-color-secondary);
|
||
font-size: 13px;
|
||
}
|
||
|
||
.application-form {
|
||
padding-right: 8px;
|
||
}
|
||
|
||
.full-width {
|
||
width: 100%;
|
||
}
|
||
|
||
.dialog-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 12px;
|
||
}
|
||
</style>
|