|
|
@@ -0,0 +1,926 @@
|
|
|
+<script setup lang="tsx">
|
|
|
+import { ref } from 'vue';
|
|
|
+import { NButton, NSpin, NTag, useMessage } from 'naive-ui';
|
|
|
+import type { TreeOption } from 'naive-ui';
|
|
|
+import {
|
|
|
+ fetchAreaDetail,
|
|
|
+ fetchAreaRule,
|
|
|
+ fetchCheckAreaRule,
|
|
|
+ fetchConfig,
|
|
|
+ fetchDelAreaRule,
|
|
|
+ fetchDelMemberRule,
|
|
|
+ fetchDelUserRule,
|
|
|
+ fetchMemberDetail,
|
|
|
+ fetchMemberList,
|
|
|
+ fetchMemberRule,
|
|
|
+ fetchProvince,
|
|
|
+ fetchSaveAreaRule,
|
|
|
+ fetchSaveConfig,
|
|
|
+ fetchSaveMemberRule,
|
|
|
+ fetchSaveTypeRule,
|
|
|
+ fetchSaveUserRule,
|
|
|
+ fetchTypeList,
|
|
|
+ fetchTypeRule,
|
|
|
+ fetchUpdateAreaRule,
|
|
|
+ fetchUpdateAreaStatus,
|
|
|
+ fetchUpdateMemberRule,
|
|
|
+ fetchUpdateMemberStatus,
|
|
|
+ fetchUpdateUserRule,
|
|
|
+ fetchUpdateUserStatus,
|
|
|
+ fetchUserDetail,
|
|
|
+ fetchUserList,
|
|
|
+ fetchUserRule
|
|
|
+} from '@/service/api/xsb-manage/free-ship';
|
|
|
+import { useModalFrom } from '@/components/zt/ModalForm/hooks/useModalForm';
|
|
|
+import { useTable } from '@/components/zt/Table/hooks/useTable';
|
|
|
+const message = useMessage();
|
|
|
+const config = ref({
|
|
|
+ isEnabled: 0, // 总开关: 0-关闭, 1-开启
|
|
|
+ calcBasis: 1, // 1-实付金额, 2-商品价格
|
|
|
+ refundPolicy: 0 // : 0-关闭(不支持部分退款免邮), 1-开启
|
|
|
+});
|
|
|
+const userOptions = ref<any[]>([]);
|
|
|
+const memberOptions = ref<any[]>([]);
|
|
|
+const defaultCheckedKeys = ref<any[]>([]);
|
|
|
+const treeData = ref<TreeOption[]>([]);
|
|
|
+
|
|
|
+const treeLoading = ref(true);
|
|
|
+const typeRule = ref<any[]>([]);
|
|
|
+const [
|
|
|
+ registerModalForm,
|
|
|
+ {
|
|
|
+ openModal: openModalForm,
|
|
|
+ setFieldsValue: setModalFormValue,
|
|
|
+ getFieldsValue: getModalFormValue,
|
|
|
+ closeModal: closeModalForm,
|
|
|
+ setSubLoading
|
|
|
+ }
|
|
|
+] = useModalFrom({
|
|
|
+ modalConfig: {
|
|
|
+ title: '区域规则',
|
|
|
+ isShowHeaderText: false
|
|
|
+ },
|
|
|
+ formConfig: {
|
|
|
+ schemas: [
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'id',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'ruleName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'updateTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'createTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'tenantId',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'ruleName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'regionType',
|
|
|
+ label: '区域类型',
|
|
|
+ component: 'NSelect',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ options: [
|
|
|
+ {
|
|
|
+ label: '省内',
|
|
|
+ value: 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '省外',
|
|
|
+ value: 2
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '指定省份',
|
|
|
+ value: 3
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ placeholder: '请选择'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'ruleName',
|
|
|
+ label: '省份类型',
|
|
|
+ component: 'ApiSelect',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ api: fetchProvince,
|
|
|
+ labelField: 'provinceName',
|
|
|
+ valueField: 'provinceName',
|
|
|
+ placeholder: '请选择'
|
|
|
+ },
|
|
|
+ ifShow({ model }) {
|
|
|
+ return model.regionType == 3;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'thresholdAmount',
|
|
|
+ label: '门槛金额',
|
|
|
+ component: 'NInputNumber',
|
|
|
+ componentProps: {
|
|
|
+ placeholder: '请输入',
|
|
|
+ precision: 2
|
|
|
+ },
|
|
|
+ suffix: 'desc-suffix',
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'regionStatus',
|
|
|
+ label: '状态',
|
|
|
+ component: 'NSwitch',
|
|
|
+ defaultValue: 1,
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ checkedValue: 1,
|
|
|
+ uncheckedValue: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ labelWidth: 120,
|
|
|
+ layout: 'horizontal',
|
|
|
+ gridProps: {
|
|
|
+ cols: '1',
|
|
|
+ itemResponsive: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const [
|
|
|
+ registerUserModalForm,
|
|
|
+ {
|
|
|
+ openModal: openUserModalForm,
|
|
|
+ setFieldsValue: setUserModalFormValue,
|
|
|
+ getFieldsValue: getUserModalFormValue,
|
|
|
+ closeModal: closeUserModal,
|
|
|
+ setSubLoading: setUserSubLoading
|
|
|
+ }
|
|
|
+] = useModalFrom({
|
|
|
+ modalConfig: {
|
|
|
+ title: '身份规则',
|
|
|
+ isShowHeaderText: false
|
|
|
+ },
|
|
|
+ formConfig: {
|
|
|
+ schemas: [
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'id',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'ruleName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'updateTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'createTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'tenantId',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'identityName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'identityId',
|
|
|
+ label: '身份类型',
|
|
|
+ component: 'ApiSelect',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ api: fetchUserList,
|
|
|
+ labelField: 'channelName',
|
|
|
+ valueField: 'id',
|
|
|
+ placeholder: '请选择',
|
|
|
+ getOptions: async (options: any) => {
|
|
|
+ userOptions.value = options;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'thresholdAmount',
|
|
|
+ label: '门槛金额',
|
|
|
+ component: 'NInputNumber',
|
|
|
+ componentProps: {
|
|
|
+ placeholder: '请输入',
|
|
|
+ precision: 2
|
|
|
+ },
|
|
|
+ suffix: 'desc-suffix',
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'identityStatus',
|
|
|
+ label: '状态',
|
|
|
+ component: 'NSwitch',
|
|
|
+ defaultValue: 1,
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ checkedValue: 1,
|
|
|
+ uncheckedValue: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ labelWidth: 120,
|
|
|
+ layout: 'horizontal',
|
|
|
+ gridProps: {
|
|
|
+ cols: '1',
|
|
|
+ itemResponsive: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const [
|
|
|
+ registerMemberModalForm,
|
|
|
+ {
|
|
|
+ openModal: openMemberModalForm,
|
|
|
+ setFieldsValue: setMemberModalFormValue,
|
|
|
+ getFieldsValue: getMemberModalFormValue,
|
|
|
+ closeModal: closeMemberModal,
|
|
|
+ setSubLoading: setMemberSubLoading
|
|
|
+ }
|
|
|
+] = useModalFrom({
|
|
|
+ modalConfig: {
|
|
|
+ title: '会员身份规则',
|
|
|
+ isShowHeaderText: false
|
|
|
+ },
|
|
|
+ formConfig: {
|
|
|
+ schemas: [
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'id',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'ruleName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'updateTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'createTime',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'tenantId',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '',
|
|
|
+ field: 'identityName',
|
|
|
+ component: 'NInput',
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'identityId',
|
|
|
+ label: '身份类型',
|
|
|
+ component: 'ApiSelect',
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ api: fetchMemberList,
|
|
|
+ labelField: 'memberName',
|
|
|
+ valueField: 'id',
|
|
|
+ placeholder: '请选择',
|
|
|
+ getOptions: async (options: any) => {
|
|
|
+ memberOptions.value = options;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'thresholdAmount',
|
|
|
+ label: '门槛金额',
|
|
|
+ component: 'NInputNumber',
|
|
|
+ componentProps: {
|
|
|
+ placeholder: '请输入',
|
|
|
+ precision: 2
|
|
|
+ },
|
|
|
+ suffix: 'desc-suffix',
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'memberStatus',
|
|
|
+ label: '状态',
|
|
|
+ component: 'NSwitch',
|
|
|
+ defaultValue: 1,
|
|
|
+ required: true,
|
|
|
+ componentProps: {
|
|
|
+ checkedValue: 1,
|
|
|
+ uncheckedValue: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ labelWidth: 120,
|
|
|
+ layout: 'horizontal',
|
|
|
+ gridProps: {
|
|
|
+ cols: '1',
|
|
|
+ itemResponsive: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const [registerTable, { refresh }] = useTable({
|
|
|
+ tableConfig: {
|
|
|
+ showTableHeaderAction: false,
|
|
|
+ showSearch: false,
|
|
|
+ showAddButton: false,
|
|
|
+ keyField: 'id',
|
|
|
+ title: '',
|
|
|
+ showDeleteButton: false,
|
|
|
+ showPagination: false,
|
|
|
+ opWdith: 240
|
|
|
+ }
|
|
|
+});
|
|
|
+const [registerUserTable, { refresh: refreshUser }] = useTable({
|
|
|
+ tableConfig: {
|
|
|
+ showTableHeaderAction: false,
|
|
|
+ showSearch: false,
|
|
|
+ showAddButton: false,
|
|
|
+ keyField: 'id',
|
|
|
+ title: '',
|
|
|
+ showDeleteButton: false,
|
|
|
+ showPagination: false,
|
|
|
+ opWdith: 240
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const [registerMemberTable, { refresh: refreshMember }] = useTable({
|
|
|
+ tableConfig: {
|
|
|
+ showTableHeaderAction: false,
|
|
|
+ showSearch: false,
|
|
|
+ showAddButton: false,
|
|
|
+ keyField: 'id',
|
|
|
+ title: '',
|
|
|
+ showDeleteButton: false,
|
|
|
+ showPagination: false,
|
|
|
+ opWdith: 240
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const areaColumns: NaiveUI.TableColumn<Api.delivery.OrderItemElement>[] = [
|
|
|
+ {
|
|
|
+ title: '规则类型',
|
|
|
+ key: 'ruleName',
|
|
|
+ align: 'center'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '省份',
|
|
|
+ key: 'provinceName',
|
|
|
+ align: 'center',
|
|
|
+ render: row => {
|
|
|
+ return row.provinceName || '--';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '门槛金额',
|
|
|
+ align: 'center',
|
|
|
+ key: 'thresholdAmount',
|
|
|
+ render: row => {
|
|
|
+ return `¥${row.thresholdAmount}`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ align: 'center',
|
|
|
+ key: 'regionStatus',
|
|
|
+ render: row => {
|
|
|
+ return row.regionStatus === 1 ? '启用' : '停用';
|
|
|
+ }
|
|
|
+ }
|
|
|
+];
|
|
|
+
|
|
|
+const userColumns: NaiveUI.TableColumn<Api.delivery.OrderItemElement>[] = [
|
|
|
+ {
|
|
|
+ title: '用户身份',
|
|
|
+ key: 'identityName',
|
|
|
+ align: 'center'
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ title: '门槛金额',
|
|
|
+ align: 'center',
|
|
|
+ key: 'thresholdAmount',
|
|
|
+ render: row => {
|
|
|
+ return `¥${row.thresholdAmount}`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ align: 'center',
|
|
|
+ key: 'identityStatus',
|
|
|
+ render: row => {
|
|
|
+ return row.identityStatus === 1 ? '启用' : '停用';
|
|
|
+ }
|
|
|
+ }
|
|
|
+];
|
|
|
+
|
|
|
+const memberColumns: NaiveUI.TableColumn<Api.delivery.OrderItemElement>[] = [
|
|
|
+ {
|
|
|
+ title: '用户身份',
|
|
|
+ key: 'identityName',
|
|
|
+ align: 'center'
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ title: '门槛金额',
|
|
|
+ align: 'center',
|
|
|
+ key: 'thresholdAmount',
|
|
|
+ render: row => {
|
|
|
+ return `¥${row.thresholdAmount}`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ align: 'center',
|
|
|
+ key: 'memberStatus',
|
|
|
+ render: row => {
|
|
|
+ return row.memberStatus === 1 ? '启用' : '停用';
|
|
|
+ }
|
|
|
+ }
|
|
|
+];
|
|
|
+
|
|
|
+async function handleEdit(row: any) {
|
|
|
+ // 编辑逻辑待实现
|
|
|
+ openModalForm();
|
|
|
+ const { data } = await fetchAreaDetail({ id: row.id });
|
|
|
+ setModalFormValue(data);
|
|
|
+}
|
|
|
+
|
|
|
+function handleDelete(row: any) {
|
|
|
+ // 删除逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: '你确定要删除吗?',
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchDelAreaRule({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refresh();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleDisable(row: any) {
|
|
|
+ // 停用逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: `你确定要${row.regionStatus === 1 ? '停用' : '启用'}吗?`,
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchUpdateAreaStatus({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refresh();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+async function handleValidateClick(e: MouseEvent) {
|
|
|
+ e.preventDefault();
|
|
|
+ const res = await fetchSaveConfig(config.value);
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('保存成功');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function getConfig() {
|
|
|
+ const res = await fetchConfig();
|
|
|
+ console.log(res, 'res');
|
|
|
+ if (!res.error) {
|
|
|
+ config.value = res.data;
|
|
|
+ }
|
|
|
+}
|
|
|
+getConfig();
|
|
|
+async function handleSubmit() {
|
|
|
+ const form = await getModalFormValue();
|
|
|
+ console.log('submit', form);
|
|
|
+
|
|
|
+ setSubLoading(true);
|
|
|
+ if (form.id) {
|
|
|
+ // 编辑
|
|
|
+ fetchUpdateAreaRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('编辑成功');
|
|
|
+ closeModalForm();
|
|
|
+ refresh();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const { error } = await fetchCheckAreaRule(form);
|
|
|
+ if (error) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 新增
|
|
|
+ fetchSaveAreaRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('新增成功');
|
|
|
+ closeModalForm();
|
|
|
+ refresh();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// -------------身份----------------
|
|
|
+
|
|
|
+// 身份
|
|
|
+async function handleUserSubmit() {
|
|
|
+ const form = await getUserModalFormValue();
|
|
|
+ console.log('submit', form);
|
|
|
+ form.identityName = userOptions.value.find((item: any) => String(item.id) === String(form.identityId))?.channelName;
|
|
|
+
|
|
|
+ setUserSubLoading(true);
|
|
|
+ if (form.id) {
|
|
|
+ // 编辑
|
|
|
+ fetchUpdateUserRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('编辑成功');
|
|
|
+ closeUserModal();
|
|
|
+ refreshUser();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 新增
|
|
|
+ fetchSaveUserRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('新增成功');
|
|
|
+ closeUserModal();
|
|
|
+ refreshUser();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function handleEditUser(row: any) {
|
|
|
+ // 编辑逻辑待实现
|
|
|
+ openUserModalForm();
|
|
|
+ const { data } = await fetchUserDetail({ id: row.id });
|
|
|
+ setUserModalFormValue(data);
|
|
|
+}
|
|
|
+
|
|
|
+function handleDeleteUser(row: any) {
|
|
|
+ // 删除逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: '你确定要删除吗?',
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchDelUserRule({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refreshUser();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleDisableUser(row: any) {
|
|
|
+ // 停用逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: `你确定要${row.identityStatus === 1 ? '停用' : '启用'}吗?`,
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchUpdateUserStatus({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refreshUser();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// -------------会员----------------
|
|
|
+
|
|
|
+// 身份
|
|
|
+async function handleMemberSubmit() {
|
|
|
+ const form = await getMemberModalFormValue();
|
|
|
+ console.log('submit', form);
|
|
|
+ form.identityName = memberOptions.value.find((item: any) => String(item.id) === String(form.identityId))?.memberName;
|
|
|
+
|
|
|
+ setMemberSubLoading(true);
|
|
|
+ if (form.id) {
|
|
|
+ // 编辑
|
|
|
+ fetchUpdateMemberRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('编辑成功');
|
|
|
+ closeMemberModal();
|
|
|
+ refreshMember();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 新增
|
|
|
+ fetchSaveMemberRule(form).then(res => {
|
|
|
+ if (!res.error) {
|
|
|
+ message.success('新增成功');
|
|
|
+ closeMemberModal();
|
|
|
+ refreshMember();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function handleEditMember(row: any) {
|
|
|
+ // 编辑逻辑待实现
|
|
|
+ openMemberModalForm();
|
|
|
+ const { data } = await fetchMemberDetail({ id: row.id });
|
|
|
+ setMemberModalFormValue(data);
|
|
|
+}
|
|
|
+
|
|
|
+function handleDeleteMember(row: any) {
|
|
|
+ // 删除逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: '你确定要删除吗?',
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchDelMemberRule({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refreshMember();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleDisableMember(row: any) {
|
|
|
+ // 停用逻辑待实现
|
|
|
+ window.$dialog?.info({
|
|
|
+ title: '提示',
|
|
|
+ content: `你确定要${row.memberStatus === 1 ? '停用' : '启用'}吗?`,
|
|
|
+ positiveText: '确定',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ const { error } = await fetchUpdateMemberStatus({ id: row.id });
|
|
|
+ if (!error) {
|
|
|
+ refreshMember();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------分类-----------------------
|
|
|
+function updateCheckedKeys(_keys: Array<string | number>, options: Array<TreeOption | null>) {
|
|
|
+ typeRule.value = options.map(item => {
|
|
|
+ return {
|
|
|
+ categoryId: item?.id,
|
|
|
+ categoryName: item?.name,
|
|
|
+ parentCategoryId: item?.pid,
|
|
|
+ shopId: item?.shopId
|
|
|
+ };
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+async function getTreeData() {
|
|
|
+ const { data } = await fetchTypeList();
|
|
|
+ treeData.value = data;
|
|
|
+}
|
|
|
+
|
|
|
+async function getTypeRule() {
|
|
|
+ const { data } = await fetchTypeRule();
|
|
|
+ typeRule.value = data;
|
|
|
+ data.forEach((item: any) => {
|
|
|
+ defaultCheckedKeys.value.push(item.categoryId);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+async function initTree() {
|
|
|
+ treeLoading.value = true;
|
|
|
+ await Promise.all([getTreeData(), getTypeRule()]);
|
|
|
+ treeLoading.value = false;
|
|
|
+}
|
|
|
+initTree();
|
|
|
+
|
|
|
+async function submitType() {
|
|
|
+ treeLoading.value = true;
|
|
|
+ const { error } = await fetchSaveTypeRule(typeRule.value);
|
|
|
+ if (!error) {
|
|
|
+ message.success('保存成功');
|
|
|
+
|
|
|
+ await getTypeRule();
|
|
|
+ treeLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function removeCategory(id: string | number) {
|
|
|
+ defaultCheckedKeys.value = defaultCheckedKeys.value.filter(key => key !== id);
|
|
|
+ typeRule.value = typeRule.value.filter(item => item.categoryId !== id);
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="flex-col-stretch">
|
|
|
+ <NCard :bordered="false" class="mb-20px flex-shrink-0">
|
|
|
+ <div class="mb-20px text-16px font-bold">基础设置</div>
|
|
|
+ <NForm
|
|
|
+ :model="config"
|
|
|
+ label-placement="left"
|
|
|
+ label-width="auto"
|
|
|
+ require-mark-placement="right-hanging"
|
|
|
+ size="medium"
|
|
|
+ class="max-w-640px"
|
|
|
+ >
|
|
|
+ <NFormItem label="启用免邮功能">
|
|
|
+ <NSwitch v-model:value="config.isEnabled" :checked-value="1" :unchecked-value="0" />
|
|
|
+ <div class="text-12px text-#ccc">(关闭后所有免邮规则不生效,订单运费恢复正常计费)</div>
|
|
|
+ </NFormItem>
|
|
|
+ <NFormItem label="计算基准">
|
|
|
+ <NRadioGroup v-model:value="config.calcBasis">
|
|
|
+ <NRadio :value="1">实付金额</NRadio>
|
|
|
+ <NRadio :value="2">商品价格</NRadio>
|
|
|
+ </NRadioGroup>
|
|
|
+ </NFormItem>
|
|
|
+ <NFormItem label="免邮退款限制">
|
|
|
+ <NSwitch v-model:value="config.refundPolicy" :checked-value="1" :unchecked-value="0" />
|
|
|
+ <div class="text-12px text-#ccc">(开启后免邮订单仅支持整单退款,不允许部分退款)</div>
|
|
|
+ </NFormItem>
|
|
|
+ <NFormItem>
|
|
|
+ <NButton attr-type="button" type="primary" size="small" @click="handleValidateClick">保存设置</NButton>
|
|
|
+ </NFormItem>
|
|
|
+ </NForm>
|
|
|
+ </NCard>
|
|
|
+ <div class="rounded-8px bg-#fff p-10px">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div class="text-16px font-bold">区域门槛规则</div>
|
|
|
+ <div class="text-12px text-#ccc">
|
|
|
+ (根据收货地址区域设置不同的免邮门槛,若 规则命中"指定省份"规则后不再向上匹配)
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <NButton type="primary" size="small" @click="openModalForm">+添加区域</NButton>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <LayoutTable class="mh-200 mb-20px">
|
|
|
+ <ZTable :columns="areaColumns" :api="fetchAreaRule" @register="registerTable">
|
|
|
+ <template #op="{ row }">
|
|
|
+ <NSpace>
|
|
|
+ <NButton size="small" type="primary" @click="handleEdit(row)">编辑</NButton>
|
|
|
+ <NButton size="small" @click="handleDisable(row)">{{ row.regionStatus == 1 ? '停用' : '启用' }}</NButton>
|
|
|
+ <NButton size="small" type="error" @click="handleDelete(row)">删除</NButton>
|
|
|
+ </NSpace>
|
|
|
+ </template>
|
|
|
+ </ZTable>
|
|
|
+ </LayoutTable>
|
|
|
+ <BasicModelForm @register-modal-form="registerModalForm" @submit-form="handleSubmit">
|
|
|
+ <template #desc-suffix="{}">
|
|
|
+ <span>设为0元表示包邮</span>
|
|
|
+ </template>
|
|
|
+ </BasicModelForm>
|
|
|
+
|
|
|
+ <div class="rounded-8px bg-#fff p-10px">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div class="text-16px font-bold">用户身份规则</div>
|
|
|
+ <div class="text-12px text-#ccc">
|
|
|
+ (根据不同身份等级的用户配置专属免邮策略,若同一用户命中多条身份规则时,取最低门槛金额)
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <NButton type="primary" size="small" @click="openUserModalForm">+添加身份</NButton>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <LayoutTable class="mh-200 mb-20px">
|
|
|
+ <ZTable :columns="userColumns" :api="fetchUserRule" @register="registerUserTable">
|
|
|
+ <template #op="{ row }">
|
|
|
+ <NSpace>
|
|
|
+ <NButton size="small" type="primary" @click="handleEditUser(row)">编辑</NButton>
|
|
|
+ <NButton size="small" @click="handleDisableUser(row)">
|
|
|
+ {{ row.identityStatus == 1 ? '停用' : '启用' }}
|
|
|
+ </NButton>
|
|
|
+ <NButton size="small" type="error" @click="handleDeleteUser(row)">删除</NButton>
|
|
|
+ </NSpace>
|
|
|
+ </template>
|
|
|
+ </ZTable>
|
|
|
+ </LayoutTable>
|
|
|
+ <BasicModelForm @register-modal-form="registerUserModalForm" @submit-form="handleUserSubmit">
|
|
|
+ <template #desc-suffix="{}">
|
|
|
+ <span>设为0元表示包邮</span>
|
|
|
+ </template>
|
|
|
+ </BasicModelForm>
|
|
|
+
|
|
|
+ <!------------ 会员------------ -->
|
|
|
+
|
|
|
+ <div class="rounded-8px bg-#fff p-10px">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div class="text-16px font-bold">会员身份规则</div>
|
|
|
+ <div class="text-12px text-#ccc">
|
|
|
+ (根据不同身份等级的用户配置专属免邮策略,若同一用户命中多条身份规则时,取最低门槛金额)
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <NButton type="primary" size="small" @click="openMemberModalForm">+添加身份</NButton>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <LayoutTable class="mh-200 mb-20px">
|
|
|
+ <ZTable :columns="memberColumns" :api="fetchMemberRule" @register="registerMemberTable">
|
|
|
+ <template #op="{ row }">
|
|
|
+ <NSpace>
|
|
|
+ <NButton size="small" type="primary" @click="handleEditMember(row)">编辑</NButton>
|
|
|
+ <NButton size="small" @click="handleDisableMember(row)">
|
|
|
+ {{ row.memberStatus == 1 ? '停用' : '启用' }}
|
|
|
+ </NButton>
|
|
|
+ <NButton size="small" type="error" @click="handleDeleteMember(row)">删除</NButton>
|
|
|
+ </NSpace>
|
|
|
+ </template>
|
|
|
+ </ZTable>
|
|
|
+ </LayoutTable>
|
|
|
+ <BasicModelForm @register-modal-form="registerMemberModalForm" @submit-form="handleMemberSubmit">
|
|
|
+ <template #desc-suffix="{}">
|
|
|
+ <span>设为0元表示包邮</span>
|
|
|
+ </template>
|
|
|
+ </BasicModelForm>
|
|
|
+
|
|
|
+ <!--------------- 分类 ---------------------->
|
|
|
+ <NCard :bordered="false" class="mb-20px flex-shrink-0">
|
|
|
+ <div class="flex items-center rounded-8px bg-#fff">
|
|
|
+ <div class="text-16px font-bold">商品类目规则</div>
|
|
|
+ <div class="text-12px text-#ccc">(选择参与免邮的商品类目)</div>
|
|
|
+ </div>
|
|
|
+ <div class="flex">
|
|
|
+ <div class="w-400px">
|
|
|
+ <NSpin :show="treeLoading">
|
|
|
+ <NTree
|
|
|
+ v-model:checked-keys="defaultCheckedKeys"
|
|
|
+ block-line
|
|
|
+ cascade
|
|
|
+ checkable
|
|
|
+ :selectable="false"
|
|
|
+ check-strategy="child"
|
|
|
+ :data="treeData"
|
|
|
+ key-field="id"
|
|
|
+ label-field="name"
|
|
|
+ default-expand-all
|
|
|
+ @update:checked-keys="updateCheckedKeys"
|
|
|
+ />
|
|
|
+ </NSpin>
|
|
|
+ </div>
|
|
|
+ <div class="ml-12px min-h-400px flex-1 border-1px border-#e8e8e8 rounded-8px bg-#fafafa p-12px">
|
|
|
+ <div class="mb-8px text-14px text-#333 font-bold">已选包邮类目</div>
|
|
|
+ <div class="flex flex-wrap content-start items-start gap-6px">
|
|
|
+ <NTag v-for="item in typeRule" :key="item.categoryId" closable @close="removeCategory(item.categoryId)">
|
|
|
+ {{ item.categoryName }}
|
|
|
+ </NTag>
|
|
|
+ <span v-if="!typeRule.length" class="text-12px text-#999">暂未选择</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <NButton :loading="treeLoading" type="primary" size="small" @click="submitType">保存设置</NButton>
|
|
|
+ </NCard>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.mh-200 {
|
|
|
+ min-height: 200px !important;
|
|
|
+}
|
|
|
+</style>
|