|
@@ -0,0 +1,382 @@
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { computed, ref, watch } from 'vue';
|
|
|
|
|
+
|
|
|
|
|
+import { $t } from '@/locales';
|
|
|
|
|
+import {
|
|
|
|
|
+ Button,
|
|
|
|
|
+ DatePicker,
|
|
|
|
|
+ Input,
|
|
|
|
|
+ message,
|
|
|
|
|
+ Modal,
|
|
|
|
|
+ Switch,
|
|
|
|
|
+ Upload,
|
|
|
|
|
+} from 'antdv-next';
|
|
|
|
|
+import MD5 from 'crypto-js/md5';
|
|
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
|
+
|
|
|
|
|
+import { createPartnerApi, getLangByKeyApi, updatePartnerApi } from '#/api';
|
|
|
|
|
+
|
|
|
|
|
+interface Props {
|
|
|
|
|
+ open: boolean;
|
|
|
|
|
+ mode: 'add' | 'edit';
|
|
|
|
|
+ partnerData?: any;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const props = defineProps<Props>();
|
|
|
|
|
+
|
|
|
|
|
+const emit = defineEmits<{
|
|
|
|
|
+ (e: 'save', data: any): void;
|
|
|
|
|
+ (e: 'update:open', value: boolean): void;
|
|
|
|
|
+}>();
|
|
|
|
|
+
|
|
|
|
|
+const token = localStorage.getItem('token_a');
|
|
|
|
|
+
|
|
|
|
|
+const formData = ref({
|
|
|
|
|
+ id: '',
|
|
|
|
|
+ logo: null,
|
|
|
|
|
+ fileId: '',
|
|
|
|
|
+ imgPhotoFileId: '',
|
|
|
|
|
+ fileList: [] as any[],
|
|
|
|
|
+ account: '',
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ nameCn: '',
|
|
|
|
|
+ nameEn: '',
|
|
|
|
|
+ langName: '',
|
|
|
|
|
+ isEnabled: true,
|
|
|
|
|
+ expiredTime: null as any,
|
|
|
|
|
+ number0fEnterprise: 0,
|
|
|
|
|
+ number0fWorkFlow: 0,
|
|
|
|
|
+ number0fPages: 0,
|
|
|
|
|
+ number0fTables: 0,
|
|
|
|
|
+ number0fDesigners: 0,
|
|
|
|
|
+ number0fBusinessScenarios: 0,
|
|
|
|
|
+ number0fCSiteMaxUser: 0,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const isOpen = computed({
|
|
|
|
|
+ get: () => props.open,
|
|
|
|
|
+ set: (value) => emit('update:open', value),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => props.open,
|
|
|
|
|
+ (newValue) => {
|
|
|
|
|
+ if (newValue && props.partnerData) {
|
|
|
|
|
+ fetchPartnerDetail();
|
|
|
|
|
+ } else if (newValue) {
|
|
|
|
|
+ resetForm();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+async function fetchPartnerDetail() {
|
|
|
|
|
+ if (!props.partnerData) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ formData.value.id = props.partnerData.id || '';
|
|
|
|
|
+ formData.value.account = props.partnerData.account || '';
|
|
|
|
|
+ formData.value.langName = props.partnerData.langName || '';
|
|
|
|
|
+ formData.value.isEnabled = props.partnerData.status ?? true;
|
|
|
|
|
+ formData.value.expiredTime = props.partnerData.expiredTime
|
|
|
|
|
+ ? dayjs(props.partnerData.expiredTime)
|
|
|
|
|
+ : null;
|
|
|
|
|
+ formData.value.number0fEnterprise = props.partnerData.number0fEnterprise || 0;
|
|
|
|
|
+ formData.value.number0fWorkFlow = props.partnerData.number0fWorkFlow || 0;
|
|
|
|
|
+ formData.value.number0fPages = props.partnerData.number0fPages || 0;
|
|
|
|
|
+ formData.value.number0fTables = props.partnerData.number0fTables || 0;
|
|
|
|
|
+ formData.value.number0fDesigners = props.partnerData.number0fDesigners || 0;
|
|
|
|
|
+ formData.value.number0fBusinessScenarios =
|
|
|
|
|
+ props.partnerData.number0fBusinessScenarios || 0;
|
|
|
|
|
+ formData.value.number0fCSiteMaxUser =
|
|
|
|
|
+ props.partnerData.number0fCSiteMaxUser || 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (props.partnerData.imgPhotoFileId) {
|
|
|
|
|
+ formData.value.imgPhotoFileId = props.partnerData.imgPhotoFileId;
|
|
|
|
|
+ formData.value.fileList = [
|
|
|
|
|
+ {
|
|
|
|
|
+ uid: '-1',
|
|
|
|
|
+ name: 'logo.png',
|
|
|
|
|
+ status: 'done',
|
|
|
|
|
+ url: `/File/Download?fileId=${props.partnerData.imgPhotoFileId}`,
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (props.mode === 'edit' && props.partnerData.langName) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const result = await getLangByKeyApi(props.partnerData.langName);
|
|
|
|
|
+ if (result?.result) {
|
|
|
|
|
+ formData.value.nameCn = result.result['zh-CN'] || '';
|
|
|
|
|
+ formData.value.nameEn = result.result.en || '';
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch {}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ formData.value.nameCn =
|
|
|
|
|
+ props.partnerData.langNameList?.find((item: any) => item.name === 'zh-CN')
|
|
|
|
|
+ ?.value || '';
|
|
|
|
|
+ formData.value.nameEn =
|
|
|
|
|
+ props.partnerData.langNameList?.find((item: any) => item.name === 'en')
|
|
|
|
|
+ ?.value || '';
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resetForm() {
|
|
|
|
|
+ formData.value = {
|
|
|
|
|
+ id: '',
|
|
|
|
|
+ logo: null,
|
|
|
|
|
+ fileId: '',
|
|
|
|
|
+ imgPhotoFileId: '',
|
|
|
|
|
+ fileList: [] as any[],
|
|
|
|
|
+ account: '',
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ nameCn: '',
|
|
|
|
|
+ nameEn: '',
|
|
|
|
|
+ langName: '',
|
|
|
|
|
+ isEnabled: true,
|
|
|
|
|
+ expiredTime: null,
|
|
|
|
|
+ number0fEnterprise: 0,
|
|
|
|
|
+ number0fWorkFlow: 0,
|
|
|
|
|
+ number0fPages: 0,
|
|
|
|
|
+ number0fTables: 0,
|
|
|
|
|
+ number0fDesigners: 0,
|
|
|
|
|
+ number0fBusinessScenarios: 0,
|
|
|
|
|
+ number0fCSiteMaxUser: 0,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleLogoUpload(info: any) {
|
|
|
|
|
+ if (info.file.status === 'done') {
|
|
|
|
|
+ formData.value.logo = info.file;
|
|
|
|
|
+ if (info.file.response?.result?.[0]?.id) {
|
|
|
|
|
+ formData.value.fileId = info.file.response.result[0].id;
|
|
|
|
|
+ formData.value.imgPhotoFileId = info.file.response.result[0].id;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function handleSave() {
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ id: formData.value.id,
|
|
|
|
|
+ langNameList: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'zh-CN',
|
|
|
|
|
+ value: formData.value.nameCn,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: 'en',
|
|
|
|
|
+ value: formData.value.nameEn,
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ fileId: formData.value.fileId,
|
|
|
|
|
+ imgPhotoFileId: formData.value.imgPhotoFileId,
|
|
|
|
|
+ version: 'v1',
|
|
|
|
|
+ account: formData.value.account,
|
|
|
|
|
+ langName:
|
|
|
|
|
+ props.mode === 'edit' ? formData.value.langName : formData.value.nameCn,
|
|
|
|
|
+ password:
|
|
|
|
|
+ props.mode === 'add' ? MD5(formData.value.password).toString() : '',
|
|
|
|
|
+ expiredTime: formData.value.expiredTime
|
|
|
|
|
+ ? formData.value.expiredTime.format('YYYY-MM-DD')
|
|
|
|
|
+ : '',
|
|
|
|
|
+ number0fEnterprise: formData.value.number0fEnterprise,
|
|
|
|
|
+ number0fPages: formData.value.number0fPages,
|
|
|
|
|
+ number0fDesigners: formData.value.number0fDesigners,
|
|
|
|
|
+ number0fCSiteMaxUser: formData.value.number0fCSiteMaxUser,
|
|
|
|
|
+ number0fBusinessScenarios: formData.value.number0fBusinessScenarios,
|
|
|
|
|
+ number0fTables: formData.value.number0fTables,
|
|
|
|
|
+ number0fWorkFlow: formData.value.number0fWorkFlow,
|
|
|
|
|
+ status: formData.value.isEnabled,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const result =
|
|
|
|
|
+ props.mode === 'add'
|
|
|
|
|
+ ? await createPartnerApi(data)
|
|
|
|
|
+ : await updatePartnerApi(data);
|
|
|
|
|
+
|
|
|
|
|
+ if (result?.isSuccess) {
|
|
|
|
|
+ message.success($t('salesPartners.saveSuccess'));
|
|
|
|
|
+ emit('save', data);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('保存失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleCancel() {
|
|
|
|
|
+ isOpen.value = false;
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+ <Modal
|
|
|
|
|
+ v-model:open="isOpen"
|
|
|
|
|
+ :footer="null"
|
|
|
|
|
+ :title="
|
|
|
|
|
+ mode === 'add'
|
|
|
|
|
+ ? $t('salesPartners.modal.addTitle')
|
|
|
|
|
+ : $t('salesPartners.modal.editTitle')
|
|
|
|
|
+ "
|
|
|
|
|
+ class="mt-[-50px]"
|
|
|
|
|
+ width="1200px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="">
|
|
|
|
|
+ <div class="flex-1 overflow-y-auto p-6">
|
|
|
|
|
+ <div class="space-y-4">
|
|
|
|
|
+ <div class="flex items-center gap-4">
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.enterpriseLogo')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Upload
|
|
|
|
|
+ v-model:file-list="formData.fileList"
|
|
|
|
|
+ :headers="{ Authorization: String(token) }"
|
|
|
|
|
+ :max-count="1"
|
|
|
|
|
+ action="/fileApi/File/UploadFiles"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ @change="handleLogoUpload"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="flex h-[100px] w-[200px] items-center justify-center border-2 border-dashed"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="text-center">
|
|
|
|
|
+ <div class="text-4xl">+</div>
|
|
|
|
|
+ <div class="text-sm text-gray-500">
|
|
|
|
|
+ {{ $t('salesPartners.modal.uploadLogo') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </Upload>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="grid grid-cols-2 gap-4">
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.account')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.account"
|
|
|
|
|
+ :placeholder="$t('salesPartners.modal.enterAccount')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="mode === 'add'" class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.password')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.password"
|
|
|
|
|
+ :placeholder="$t('salesPartners.modal.enterPassword')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.nameCn')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.nameCn"
|
|
|
|
|
+ :placeholder="$t('salesPartners.modal.enterName')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.nameEn')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.nameEn"
|
|
|
|
|
+ :placeholder="$t('salesPartners.modal.enterName')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.expiredTime')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <DatePicker
|
|
|
|
|
+ v-model:value="formData.expiredTime"
|
|
|
|
|
+ :placeholder="$t('salesPartners.modal.selectExpiredTime')"
|
|
|
|
|
+ class="h-[32px] w-full"
|
|
|
|
|
+ format="YYYY-MM-DD"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.isEnabled')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Switch v-model:checked="formData.isEnabled" class="w-[40px]" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fEnterprise')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.number0fEnterprise"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fWorkFlow')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input v-model:value="formData.number0fWorkFlow" type="number" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fPages')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input v-model:value="formData.number0fPages" type="number" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fTables')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input v-model:value="formData.number0fTables" type="number" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fDesigners')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input v-model:value="formData.number0fDesigners" type="number" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fBusinessScenarios')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.number0fBusinessScenarios"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex flex-col gap-2">
|
|
|
|
|
+ <label class="text-sm font-medium">{{
|
|
|
|
|
+ $t('salesPartners.modal.number0fCSiteMaxUser')
|
|
|
|
|
+ }}</label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ v-model:value="formData.number0fCSiteMaxUser"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="flex justify-end gap-4">
|
|
|
|
|
+ <Button @click="handleCancel">
|
|
|
|
|
+ {{ $t('salesPartners.modal.cancel') }}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button type="primary" @click="handleSave">
|
|
|
|
|
+ {{ $t('salesPartners.modal.save') }}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+:deep(.ant-upload-list-picture-card-container) {
|
|
|
|
|
+ .ant-upload-list-item {
|
|
|
|
|
+ width: 80px;
|
|
|
|
|
+ height: 80px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|