|
|
@@ -0,0 +1,383 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, ref, watch } from 'vue';
|
|
|
+
|
|
|
+import { useUserStore } from '@vben/stores';
|
|
|
+
|
|
|
+import { $t } from '@/locales';
|
|
|
+import {
|
|
|
+ Button,
|
|
|
+ Dropdown,
|
|
|
+ Empty,
|
|
|
+ Input,
|
|
|
+ message,
|
|
|
+ Modal,
|
|
|
+ Pagination,
|
|
|
+} from 'antdv-next';
|
|
|
+
|
|
|
+import { deleteEnterpriseCustomerApi, getEnterpriseCustomersApi } from '#/api';
|
|
|
+
|
|
|
+import EnterpriseCustomersModal from './enterprise-customers-modal.vue';
|
|
|
+
|
|
|
+const modalOpen = ref(false);
|
|
|
+const modalMode = ref<'add' | 'edit'>('add');
|
|
|
+const currentCustomer = ref<any>(null);
|
|
|
+
|
|
|
+const userStore = useUserStore();
|
|
|
+const isLogin = computed(() => !!userStore.userInfo);
|
|
|
+
|
|
|
+const customerList = ref<any[]>([]);
|
|
|
+const loading = ref(false);
|
|
|
+
|
|
|
+const searchParams = ref({
|
|
|
+ name: '',
|
|
|
+ code: '',
|
|
|
+ isEnable: '',
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 12,
|
|
|
+});
|
|
|
+
|
|
|
+const totalPage = ref(0);
|
|
|
+const totalCount = ref(0);
|
|
|
+
|
|
|
+function handleSearch() {
|
|
|
+ searchParams.value.currentPage = 1;
|
|
|
+ fetchEnterpriseCustomers();
|
|
|
+}
|
|
|
+
|
|
|
+function handleAddNew() {
|
|
|
+ modalMode.value = 'add';
|
|
|
+ currentCustomer.value = null;
|
|
|
+ modalOpen.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+function handleEdit(item: any) {
|
|
|
+ modalMode.value = 'edit';
|
|
|
+ currentCustomer.value = item;
|
|
|
+ modalOpen.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+function handleModalSave() {
|
|
|
+ modalOpen.value = false;
|
|
|
+ fetchEnterpriseCustomers();
|
|
|
+}
|
|
|
+
|
|
|
+function handleMenuClick({ key }: { key: string }, item: any) {
|
|
|
+ if (key === 'Edit') {
|
|
|
+ handleEdit(item);
|
|
|
+ } else if (key === 'Remove') {
|
|
|
+ Modal.confirm({
|
|
|
+ title: $t('enterpriseCustomers.deleteConfirm'),
|
|
|
+ content: $t('enterpriseCustomers.deleteDescription'),
|
|
|
+ okText: $t('btn.yes'),
|
|
|
+ okType: 'danger',
|
|
|
+ cancelText: $t('btn.no'),
|
|
|
+ onOk() {
|
|
|
+ deleteCustomer(item);
|
|
|
+ },
|
|
|
+ onCancel() {},
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function handleBack() {
|
|
|
+ window.history.back();
|
|
|
+}
|
|
|
+
|
|
|
+function handleClear() {
|
|
|
+ searchParams.value.name = '';
|
|
|
+ searchParams.value.code = '';
|
|
|
+ searchParams.value.isEnable = '';
|
|
|
+ handleSearch();
|
|
|
+}
|
|
|
+
|
|
|
+function handlePageChange(page: number) {
|
|
|
+ searchParams.value.currentPage = page;
|
|
|
+ fetchEnterpriseCustomers();
|
|
|
+}
|
|
|
+
|
|
|
+async function fetchEnterpriseCustomers() {
|
|
|
+ if (!isLogin.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+ const result = await getEnterpriseCustomersApi({
|
|
|
+ currentPage: searchParams.value.currentPage,
|
|
|
+ pageSize: searchParams.value.pageSize,
|
|
|
+ orderByProperty: 'Id',
|
|
|
+ Ascending: false,
|
|
|
+ filters: [
|
|
|
+ {
|
|
|
+ name: 'name',
|
|
|
+ value: searchParams.value.name,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'code',
|
|
|
+ value: searchParams.value.code,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'isEnable',
|
|
|
+ value: searchParams.value.isEnable,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ });
|
|
|
+ if (result?.result?.model) {
|
|
|
+ customerList.value = result.result.model;
|
|
|
+ totalPage.value = result.result.totalPages;
|
|
|
+ totalCount.value = result.result.totalCount;
|
|
|
+ }
|
|
|
+ } catch {}
|
|
|
+}
|
|
|
+
|
|
|
+async function deleteCustomer(item: any) {
|
|
|
+ if (!isLogin.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+ const result = await deleteEnterpriseCustomerApi({
|
|
|
+ code: item.code,
|
|
|
+ });
|
|
|
+ if (result?.result) {
|
|
|
+ fetchEnterpriseCustomers();
|
|
|
+ message.success($t('enterpriseCustomers.deleteSuccess'));
|
|
|
+ }
|
|
|
+ } catch {}
|
|
|
+}
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => isLogin.value,
|
|
|
+ (newValue) => {
|
|
|
+ if (newValue) {
|
|
|
+ fetchEnterpriseCustomers();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true },
|
|
|
+);
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="p-5">
|
|
|
+ <div class="mb-4 flex items-center justify-between">
|
|
|
+ <div class="text-sm text-[#462424] text-gray-500">
|
|
|
+ {{ $t('enterpriseCustomers.breadcrumb') }}
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="flex cursor-pointer items-center gap-[9px] text-[16px] font-bold text-[#462424]"
|
|
|
+ @click="handleBack"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="global-color flex h-[22px] w-[22px] items-center justify-center rounded-full"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ alt=""
|
|
|
+ class="h-[11px] w-[10px]"
|
|
|
+ src="@/assets/image/the-left.png"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ {{ $t('btn.back') }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="mb-[21px] mt-[30px] text-[26px] font-bold text-[#462424]">
|
|
|
+ {{ $t('homeModule.enterpriseCustomers') }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="mb-4 flex flex-wrap items-center gap-4">
|
|
|
+ <div class="flex flex-col gap-1">
|
|
|
+ <label class="text-[11px] text-[#000]">{{
|
|
|
+ $t('enterpriseCustomers.customerName')
|
|
|
+ }}</label>
|
|
|
+ <Input
|
|
|
+ v-model:value="searchParams.name"
|
|
|
+ class="h-[42px] w-[220px] rounded-[11px] border-[#707070]"
|
|
|
+ placeholder=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col gap-1">
|
|
|
+ <label class="text-[11px] text-[#000]">{{
|
|
|
+ $t('enterpriseCustomers.customerCode')
|
|
|
+ }}</label>
|
|
|
+ <Input
|
|
|
+ v-model:value="searchParams.code"
|
|
|
+ class="h-[42px] w-[220px] rounded-[11px] border-[#707070]"
|
|
|
+ placeholder=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- <div class="flex flex-col gap-1">
|
|
|
+ <label class="text-[11px] text-[#000]">{{
|
|
|
+ $t('enterpriseCustomers.status')
|
|
|
+ }}</label>
|
|
|
+ <Select
|
|
|
+ v-model:value="searchParams.isEnable"
|
|
|
+ :options="[
|
|
|
+ { value: '1', label: $t('enterpriseCustomers.active') },
|
|
|
+ { value: '0', label: $t('enterpriseCustomers.inactive') }
|
|
|
+ ]"
|
|
|
+ placeholder="{{ $t('enterpriseCustomers.chooseStatus') }}"
|
|
|
+ class="h-[42px] w-[168px] rounded-[11px] border-[#707070] text-[12px]"
|
|
|
+ />
|
|
|
+ </div> -->
|
|
|
+ <div class="ml-auto flex items-center gap-2">
|
|
|
+ <Button class="h-[42px]" @click="handleSearch">
|
|
|
+ <svg
|
|
|
+ class="h-[21.5px] w-[21.5px] cursor-pointer"
|
|
|
+ fill="none"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ >
|
|
|
+ <circle
|
|
|
+ cx="11"
|
|
|
+ cy="11"
|
|
|
+ r="8"
|
|
|
+ stroke="currentColor"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ <path
|
|
|
+ d="M21 21L16.65 16.65"
|
|
|
+ stroke="currentColor"
|
|
|
+ stroke-linecap="round"
|
|
|
+ stroke-linejoin="round"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ {{ $t('btn.search') }}
|
|
|
+ </Button>
|
|
|
+ <Button class="h-[42px]" @click="handleClear">
|
|
|
+ <svg
|
|
|
+ class="h-[21.5px] w-[21.5px] cursor-pointer"
|
|
|
+ fill="none"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ >
|
|
|
+ <path
|
|
|
+ d="M3 6H5"
|
|
|
+ stroke="currentColor"
|
|
|
+ stroke-linecap="round"
|
|
|
+ stroke-linejoin="round"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ <path
|
|
|
+ d="M19 6V20C19 21.1046 18.1046 22 17 22H7C5.89543 22 5 21.1046 5 20V6M8 6V4C8 3.79086 8.79086 3 10 3H14C15.2091 3 16 3.79086 16 6V8M10 11V17M14 11V17"
|
|
|
+ stroke="currentColor"
|
|
|
+ stroke-linecap="round"
|
|
|
+ stroke-linejoin="round"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ {{ $t('btn.reset') }}
|
|
|
+ </Button>
|
|
|
+ <Button class="h-[42px]" type="primary" @click="handleAddNew">
|
|
|
+ <img
|
|
|
+ alt=""
|
|
|
+ class="h-[21.5px] w-[21.5px] cursor-pointer"
|
|
|
+ src="@/assets/image/new.png"
|
|
|
+ />
|
|
|
+ {{ $t('btn.addNew') }}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- <div class="w-[722px] h-[auto] z-[-1] absolute top-[0] right-[0]">
|
|
|
+ <img src="@/assets/image/list1.png" class="w-full h-full object-cover" alt="">
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <div v-if="loading" class="py-8 text-center">
|
|
|
+ {{ $t('enterpriseCustomers.loading') }}
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-else-if="customerList.length === 0"
|
|
|
+ class="mt-[100px] py-8 text-center text-gray-500"
|
|
|
+ >
|
|
|
+ <Empty />
|
|
|
+ </div>
|
|
|
+ <div v-else class="mb-[76px] mt-[38px] flex flex-wrap gap-[18px]">
|
|
|
+ <div
|
|
|
+ v-for="item in customerList"
|
|
|
+ :key="item.id"
|
|
|
+ class="flex h-[78px] cursor-pointer items-center gap-[25px] rounded-[11px] bg-[#fff] px-[20px] shadow-md"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ v-if="item.imgPhotoFileId"
|
|
|
+ :src="`/File/Download?fileId=${item.imgPhotoFileId}`"
|
|
|
+ alt=""
|
|
|
+ class="h-[48px] w-auto object-contain"
|
|
|
+ />
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ class="flex h-[48px] w-[48px] items-center justify-center rounded bg-gray-200"
|
|
|
+ >
|
|
|
+ <svg
|
|
|
+ class="h-6 w-6 text-gray-400"
|
|
|
+ fill="none"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ xmlns="http://www.w3.org/2000/svg"
|
|
|
+ >
|
|
|
+ <path
|
|
|
+ d="M12 16V12M12 8H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z"
|
|
|
+ stroke="currentColor"
|
|
|
+ stroke-linecap="round"
|
|
|
+ stroke-linejoin="round"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ <!-- <div class="flex-1">
|
|
|
+ <div class="text-sm font-bold">{{ item.name }}</div>
|
|
|
+ <div class="text-xs text-gray-500">{{ item.code }}</div>
|
|
|
+ <div v-if="item.partnerUserName" class="text-xs text-gray-500">合作伙伴: {{ item.partnerUserName }}</div>
|
|
|
+ </div> -->
|
|
|
+ <Dropdown
|
|
|
+ :menu="{
|
|
|
+ items: [
|
|
|
+ { key: 'Edit', label: $t('enterpriseCustomers.edit') },
|
|
|
+ { key: 'Remove', label: $t('enterpriseCustomers.remove') },
|
|
|
+ ],
|
|
|
+ }"
|
|
|
+ placement="bottom"
|
|
|
+ @menu-click="(info: any) => handleMenuClick(info, item)"
|
|
|
+ >
|
|
|
+ <div class="flex cursor-pointer items-center gap-2">
|
|
|
+ <img
|
|
|
+ alt=""
|
|
|
+ class="h-[19px] w-[19px] cursor-pointer"
|
|
|
+ src="@/assets/image/more-tow.png"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </Dropdown>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="list-pagination">
|
|
|
+ <Pagination
|
|
|
+ v-model:current="searchParams.currentPage"
|
|
|
+ :hide-on-single-page="true"
|
|
|
+ :page-size="12"
|
|
|
+ :show-size-changer="false"
|
|
|
+ :total="totalCount"
|
|
|
+ @change="handlePageChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <EnterpriseCustomersModal
|
|
|
+ v-model:open="modalOpen"
|
|
|
+ :customer-data="currentCustomer"
|
|
|
+ :mode="modalMode"
|
|
|
+ @save="handleModalSave"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.ant-pagination-item-active {
|
|
|
+ color: #7a003d !important;
|
|
|
+ background-color: #f8f2f5 !important;
|
|
|
+ border-color: transparent !important;
|
|
|
+
|
|
|
+ a {
|
|
|
+ color: #c48da8 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|