1
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="商城名称" name="shopName">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="请输入商城名称"
|
||||
v-model:value="form.shopName"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商城Logo" name="shopLogo">
|
||||
<SelectFile
|
||||
:placeholder="'请选择商城Logo'"
|
||||
:limit="1"
|
||||
:data="logoList"
|
||||
@done="chooseImage"
|
||||
@del="onDeleteImage"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商城描述" name="shopDesc">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="500"
|
||||
placeholder="请输入商城描述"
|
||||
v-model:value="form.shopDesc"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="客服电话" name="shopPhone">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="请输入客服电话"
|
||||
v-model:value="form.shopPhone"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商城地址" name="shopAddress">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
placeholder="请输入商城地址"
|
||||
v-model:value="form.shopAddress"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商城开关" name="shopEnabled">
|
||||
<a-switch v-model:checked="form.shopEnabled" checked-children="开" un-checked-children="关" />
|
||||
</a-form-item>
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
const category = 'basic';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const logoList = ref<ItemType[]>([]);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
shopName: '',
|
||||
shopLogo: '',
|
||||
shopDesc: '',
|
||||
shopPhone: '',
|
||||
shopAddress: '',
|
||||
shopEnabled: true
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
shopName: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入商城名称',
|
||||
type: 'string',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// 选择图片
|
||||
const chooseImage = (data: FileRecord) => {
|
||||
logoList.value.push({ uid: data.id, url: data.path, status: 'done' });
|
||||
form.shopLogo = data.path;
|
||||
};
|
||||
|
||||
// 删除图片
|
||||
const onDeleteImage = (index: number) => {
|
||||
logoList.value.splice(index, 1);
|
||||
form.shopLogo = '';
|
||||
};
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换(后端可能返回字符串 '1'/'0'/'true'/'false')
|
||||
const raw = (values as any).shopEnabled;
|
||||
form.shopEnabled = raw === true || raw === 'true' || raw === '1' || raw === 1;
|
||||
// 回显 Logo
|
||||
logoList.value = [];
|
||||
if (form.shopLogo) {
|
||||
logoList.value.push({ uid: 1, url: form.shopLogo as string, status: '' });
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="启用分销功能" name="dealerEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.dealerEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放申请分销商" name="dealerApplyEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.dealerApplyEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="一级佣金比例" name="dealerLevel1Rate">
|
||||
<a-input-number
|
||||
v-model:value="form.dealerLevel1Rate"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入比例"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">%</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="二级佣金比例" name="dealerLevel2Rate">
|
||||
<a-input-number
|
||||
v-model:value="form.dealerLevel2Rate"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
placeholder="请输入比例"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">%</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="最低提现金额" name="dealerWithdrawMin">
|
||||
<a-input-number
|
||||
v-model:value="form.dealerWithdrawMin"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="请输入最低提现金额"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">元</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'dealer';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
dealerEnabled: false,
|
||||
dealerApplyEnabled: false,
|
||||
dealerLevel1Rate: 10,
|
||||
dealerLevel2Rate: 5,
|
||||
dealerWithdrawMin: 10
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
dealerLevel1Rate: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入一级佣金比例',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
dealerLevel2Rate: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入二级佣金比例',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
dealerWithdrawMin: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入最低提现金额',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const toBool = (val: any): boolean =>
|
||||
val === true || val === 'true' || val === '1' || val === 1;
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换
|
||||
form.dealerEnabled = toBool((values as any).dealerEnabled);
|
||||
form.dealerApplyEnabled = toBool((values as any).dealerApplyEnabled);
|
||||
// 数值字段转换
|
||||
if (values.dealerLevel1Rate !== undefined) {
|
||||
form.dealerLevel1Rate = Number(values.dealerLevel1Rate);
|
||||
}
|
||||
if (values.dealerLevel2Rate !== undefined) {
|
||||
form.dealerLevel2Rate = Number(values.dealerLevel2Rate);
|
||||
}
|
||||
if (values.dealerWithdrawMin !== undefined) {
|
||||
form.dealerWithdrawMin = Number(values.dealerWithdrawMin);
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,206 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-divider orientation="left">小程序基础信息</a-divider>
|
||||
<a-form-item label="AppID" name="miniAppId">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="请输入微信小程序 AppID"
|
||||
v-model:value="form.miniAppId"
|
||||
/>
|
||||
<div class="ant-form-item-explain">微信公众平台 → 开发管理 → 开发设置 → AppID</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="AppSecret" name="miniAppSecret">
|
||||
<a-input-password
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
placeholder="请输入微信小程序 AppSecret"
|
||||
v-model:value="form.miniAppSecret"
|
||||
/>
|
||||
<div class="ant-form-item-explain">用于服务端接口调用(登录、支付等),请妥善保管</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">小程序页面配置</a-divider>
|
||||
<a-form-item label="首页路径" name="miniHomePath">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
placeholder="如 pages/index/index"
|
||||
v-model:value="form.miniHomePath"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分享标题" name="miniShareTitle">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="默认分享到好友/朋友圈的标题"
|
||||
v-model:value="form.miniShareTitle"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分享图片" name="miniShareImage">
|
||||
<SelectFile
|
||||
:placeholder="'请选择分享图片'"
|
||||
:limit="1"
|
||||
:data="shareImageList"
|
||||
@done="chooseShareImage"
|
||||
@del="onDeleteShareImage"
|
||||
/>
|
||||
<div class="ant-form-item-explain">建议尺寸:500x400 像素,不超过 1MB</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">客服与联系</a-divider>
|
||||
<a-form-item label="客服开关" name="miniKfEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.miniKfEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="客服类型" name="miniKfType">
|
||||
<a-radio-group v-model:value="form.miniKfType">
|
||||
<a-radio value="button">悬浮按钮</a-radio>
|
||||
<a-radio value="menu">菜单入口</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="联系客服" name="miniContactPhone">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="30"
|
||||
placeholder="联系电话或客服微信号"
|
||||
v-model:value="form.miniContactPhone"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">订阅消息</a-divider>
|
||||
<a-form-item label="订阅开关" name="miniSubscribeEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.miniSubscribeEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="模板ID" name="miniSubscribeTemplateIds">
|
||||
<a-textarea
|
||||
:rows="3"
|
||||
:maxlength="500"
|
||||
placeholder="多个模板ID用英文逗号分隔"
|
||||
v-model:value="form.miniSubscribeTemplateIds"
|
||||
/>
|
||||
<div class="ant-form-item-explain">微信公众平台 → 功能 → 订阅消息 → 公共模板库</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { FileRecord } from '@/api/system/file/model';
|
||||
|
||||
const category = 'miniprogram';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
const shareImageList = ref<ItemType[]>([]);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
miniAppId: '',
|
||||
miniAppSecret: '',
|
||||
miniHomePath: '',
|
||||
miniShareTitle: '',
|
||||
miniShareImage: '',
|
||||
miniKfEnabled: false,
|
||||
miniKfType: 'button',
|
||||
miniContactPhone: '',
|
||||
miniSubscribeEnabled: false,
|
||||
miniSubscribeTemplateIds: ''
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
miniAppId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入微信小程序 AppID',
|
||||
type: 'string',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const toBool = (val: any): boolean =>
|
||||
val === true || val === 'true' || val === '1' || val === 1;
|
||||
|
||||
// 选择分享图片
|
||||
const chooseShareImage = (data: FileRecord) => {
|
||||
shareImageList.value.push({ uid: data.id, url: data.path, status: 'done' });
|
||||
form.miniShareImage = data.path;
|
||||
};
|
||||
|
||||
// 删除分享图片
|
||||
const onDeleteShareImage = (index: number) => {
|
||||
shareImageList.value.splice(index, 1);
|
||||
form.miniShareImage = '';
|
||||
};
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换
|
||||
form.miniKfEnabled = toBool((values as any).miniKfEnabled);
|
||||
form.miniSubscribeEnabled = toBool((values as any).miniSubscribeEnabled);
|
||||
// 回显分享图片
|
||||
shareImageList.value = [];
|
||||
if (form.miniShareImage) {
|
||||
shareImageList.value.push({ uid: 1, url: form.miniShareImage as string, status: '' });
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '120px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="订单通知" name="notifyOrderEnabled">
|
||||
<a-switch v-model:checked="form.notifyOrderEnabled" />
|
||||
<span class="ele-text-secondary" style="margin-left: 8px; font-size: 12px;">用户下单后发送通知</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="支付通知" name="notifyPayEnabled">
|
||||
<a-switch v-model:checked="form.notifyPayEnabled" />
|
||||
<span class="ele-text-secondary" style="margin-left: 8px; font-size: 12px;">用户支付成功后发送通知</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="退款通知" name="notifyRefundEnabled">
|
||||
<a-switch v-model:checked="form.notifyRefundEnabled" />
|
||||
<span class="ele-text-secondary" style="margin-left: 8px; font-size: 12px;">退款申请/完成后发送通知</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="发货通知" name="notifyShipEnabled">
|
||||
<a-switch v-model:checked="form.notifyShipEnabled" />
|
||||
<span class="ele-text-secondary" style="margin-left: 8px; font-size: 12px;">商家发货后发送通知</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="签收通知" name="notifySignEnabled">
|
||||
<a-switch v-model:checked="form.notifySignEnabled" />
|
||||
<span class="ele-text-secondary" style="margin-left: 8px; font-size: 12px;">用户确认收货后发送通知</span>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="styleResponsive ? { md: { offset: 3, span: 9 } } : { flex: '1' }">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'notify';
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
notifyOrderEnabled: true,
|
||||
notifyPayEnabled: true,
|
||||
notifyRefundEnabled: true,
|
||||
notifyShipEnabled: true,
|
||||
notifySignEnabled: true,
|
||||
});
|
||||
|
||||
const toBool = (v: any): boolean => v === true || v === 1 || v === '1' || v === 'true';
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
form.notifyOrderEnabled = toBool((values as any).notifyOrderEnabled);
|
||||
form.notifyPayEnabled = toBool((values as any).notifyPayEnabled);
|
||||
form.notifyRefundEnabled = toBool((values as any).notifyRefundEnabled);
|
||||
form.notifyShipEnabled = toBool((values as any).notifyShipEnabled);
|
||||
form.notifySignEnabled = toBool((values as any).notifySignEnabled);
|
||||
}
|
||||
} catch (e) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => { message.success('保存成功'); })
|
||||
.catch((e: any) => { message.error(e.message); })
|
||||
.finally(() => { loading.value = false; });
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="自动确认收货天数" name="orderAutoConfirmDays">
|
||||
<a-input-number
|
||||
v-model:value="form.orderAutoConfirmDays"
|
||||
:min="1"
|
||||
:max="365"
|
||||
placeholder="请输入天数"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">天</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="未付款自动关闭" name="orderAutoCloseMins">
|
||||
<a-input-number
|
||||
v-model:value="form.orderAutoCloseMins"
|
||||
:min="1"
|
||||
:max="10080"
|
||||
placeholder="请输入分钟数"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">分钟</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="自动好评天数" name="orderAutoCommentDays">
|
||||
<a-input-number
|
||||
v-model:value="form.orderAutoCommentDays"
|
||||
:min="1"
|
||||
:max="365"
|
||||
placeholder="请输入天数"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">天</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="免运费金额" name="orderFreightFreeAmount">
|
||||
<a-input-number
|
||||
v-model:value="form.orderFreightFreeAmount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="0 表示不免运费"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">元(0 表示不免运费)</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="允许退款" name="orderRefundEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.orderRefundEnabled"
|
||||
checked-children="是"
|
||||
un-checked-children="否"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'order';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
orderAutoConfirmDays: 7,
|
||||
orderAutoCloseMins: 30,
|
||||
orderAutoCommentDays: 15,
|
||||
orderFreightFreeAmount: 0,
|
||||
orderRefundEnabled: true
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
orderAutoConfirmDays: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入自动确认收货天数',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
orderAutoCloseMins: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入未付款自动关闭分钟数',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
orderAutoCommentDays: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入自动好评天数',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换
|
||||
const raw = (values as any).orderRefundEnabled;
|
||||
form.orderRefundEnabled = raw === true || raw === 'true' || raw === '1' || raw === 1;
|
||||
// 数值字段转换(后端返回字符串时)
|
||||
if (values.orderAutoConfirmDays !== undefined) {
|
||||
form.orderAutoConfirmDays = Number(values.orderAutoConfirmDays);
|
||||
}
|
||||
if (values.orderAutoCloseMins !== undefined) {
|
||||
form.orderAutoCloseMins = Number(values.orderAutoCloseMins);
|
||||
}
|
||||
if (values.orderAutoCommentDays !== undefined) {
|
||||
form.orderAutoCommentDays = Number(values.orderAutoCommentDays);
|
||||
}
|
||||
if (values.orderFreightFreeAmount !== undefined) {
|
||||
form.orderFreightFreeAmount = Number(values.orderFreightFreeAmount);
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="余额支付" name="payBalanceEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.payBalanceEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信支付" name="payWechatEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.payWechatEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信AppID" name="payWechatAppId">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="请输入微信AppID"
|
||||
v-model:value="form.payWechatAppId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信商户号" name="payWechatMchId">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="请输入微信商户号"
|
||||
v-model:value="form.payWechatMchId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="微信支付APIv3密钥" name="payWechatApiKey">
|
||||
<a-input-password
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
placeholder="请输入微信支付APIv3密钥"
|
||||
v-model:value="form.payWechatApiKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
<div style="margin-bottom: 22px; width: 750px">
|
||||
<a-divider>支付宝支付</a-divider>
|
||||
</div>
|
||||
<a-form-item label="支付宝支付" name="payAlipayEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.payAlipayEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="支付宝AppID" name="payAlipayAppId">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="请输入支付宝AppID"
|
||||
v-model:value="form.payAlipayAppId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户私钥" name="payAlipayPrivateKey">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
placeholder="请输入商户私钥"
|
||||
v-model:value="form.payAlipayPrivateKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="支付宝公钥" name="payAlipayPublicKey">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
placeholder="请输入支付宝公钥"
|
||||
v-model:value="form.payAlipayPublicKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'payment';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
payBalanceEnabled: false,
|
||||
payWechatEnabled: false,
|
||||
payWechatAppId: '',
|
||||
payWechatMchId: '',
|
||||
payWechatApiKey: '',
|
||||
payAlipayEnabled: false,
|
||||
payAlipayAppId: '',
|
||||
payAlipayPrivateKey: '',
|
||||
payAlipayPublicKey: ''
|
||||
});
|
||||
|
||||
const rules = reactive({});
|
||||
|
||||
const toBool = (val: any): boolean =>
|
||||
val === true || val === 'true' || val === '1' || val === 1;
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换
|
||||
form.payBalanceEnabled = toBool((values as any).payBalanceEnabled);
|
||||
form.payWechatEnabled = toBool((values as any).payWechatEnabled);
|
||||
form.payAlipayEnabled = toBool((values as any).payAlipayEnabled);
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="启用积分功能" name="pointsEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.pointsEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="启用签到积分" name="pointsSigninEnabled">
|
||||
<a-switch
|
||||
v-model:checked="form.pointsSigninEnabled"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="每日签到积分" name="pointsSigninAmount">
|
||||
<a-input-number
|
||||
v-model:value="form.pointsSigninAmount"
|
||||
:min="1"
|
||||
:max="99999"
|
||||
placeholder="请输入签到积分数"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">积分</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="消费积分比例" name="pointsOrderRate">
|
||||
<a-input-number
|
||||
v-model:value="form.pointsOrderRate"
|
||||
:min="1"
|
||||
:max="99999"
|
||||
placeholder="请输入比例"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">每消费 N 元得 1 积分</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="积分兑换比例" name="pointsExchangeRate">
|
||||
<a-input-number
|
||||
v-model:value="form.pointsExchangeRate"
|
||||
:min="1"
|
||||
:max="99999"
|
||||
placeholder="请输入比例"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<span style="margin-left: 8px; color: #888">N 积分兑换 1 元</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'points';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
pointsEnabled: true,
|
||||
pointsSigninEnabled: true,
|
||||
pointsSigninAmount: 10,
|
||||
pointsOrderRate: 10,
|
||||
pointsExchangeRate: 100
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
pointsSigninAmount: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入每日签到积分数',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
pointsOrderRate: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入消费积分比例',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
pointsExchangeRate: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入积分兑换比例',
|
||||
type: 'number',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const toBool = (val: any): boolean =>
|
||||
val === true || val === 'true' || val === '1' || val === 1;
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 布尔值转换
|
||||
form.pointsEnabled = toBool((values as any).pointsEnabled);
|
||||
form.pointsSigninEnabled = toBool((values as any).pointsSigninEnabled);
|
||||
// 数值字段转换
|
||||
if (values.pointsSigninAmount !== undefined) {
|
||||
form.pointsSigninAmount = Number(values.pointsSigninAmount);
|
||||
}
|
||||
if (values.pointsOrderRate !== undefined) {
|
||||
form.pointsOrderRate = Number(values.pointsOrderRate);
|
||||
}
|
||||
if (values.pointsExchangeRate !== undefined) {
|
||||
form.pointsExchangeRate = Number(values.pointsExchangeRate);
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="短信平台" name="smsType">
|
||||
<a-radio-group v-model:value="form.smsType">
|
||||
<a-radio :value="1">阿里云</a-radio>
|
||||
<a-radio :value="2">腾讯云</a-radio>
|
||||
<a-radio :value="3">七牛云</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="AccessKeyId" name="accessKeyId">
|
||||
<a-input
|
||||
v-model:value="form.accessKeyId"
|
||||
placeholder="请输入 AccessKeyId"
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="AccessKeySecret" name="accessKeySecret">
|
||||
<a-input-password
|
||||
v-model:value="form.accessKeySecret"
|
||||
placeholder="请输入 AccessKeySecret"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="短信签名" name="smsSign">
|
||||
<a-input
|
||||
v-model:value="form.smsSign"
|
||||
placeholder="请输入短信签名"
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">短信验证码(通知用户)</a-divider>
|
||||
<a-form-item label="是否开启" name="smsNoticeUser">
|
||||
<a-radio-group v-model:value="form.smsNoticeUser">
|
||||
<a-radio :value="1">开启</a-radio>
|
||||
<a-radio :value="0">关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="模板内容">
|
||||
<span class="ele-text-secondary">
|
||||
验证码 ${code},您正在进行身份验证,请勿泄露给他人!
|
||||
</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="模板ID" name="smsUserTemplateId">
|
||||
<a-input
|
||||
v-model:value="form.smsUserTemplateId"
|
||||
placeholder="请输入用户验证码模板ID"
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">新订单通知(通知商家)</a-divider>
|
||||
<a-form-item label="是否开启" name="smsNoticeMerchant">
|
||||
<a-radio-group v-model:value="form.smsNoticeMerchant">
|
||||
<a-radio :value="1">开启</a-radio>
|
||||
<a-radio :value="0">关闭</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="模板ID" name="smsMerchantTemplateId">
|
||||
<a-input
|
||||
v-model:value="form.smsMerchantTemplateId"
|
||||
placeholder="请输入商家通知模板ID"
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="接收手机号" name="smsMerchantMobiles">
|
||||
<a-input
|
||||
v-model:value="form.smsMerchantMobiles"
|
||||
placeholder="多个手机号用英文逗号分隔"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
<div class="ele-text-secondary" style="font-size: 12px">
|
||||
新订单将向以上手机号发送短信通知
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'sms';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
smsType: 1,
|
||||
accessKeyId: '',
|
||||
accessKeySecret: '',
|
||||
smsSign: '',
|
||||
smsNoticeUser: 1,
|
||||
smsUserTemplateId: '',
|
||||
smsNoticeMerchant: 1,
|
||||
smsMerchantTemplateId: '',
|
||||
smsMerchantMobiles: ''
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
accessKeyId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入 AccessKeyId',
|
||||
type: 'string',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
accessKeySecret: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入 AccessKeySecret',
|
||||
type: 'string',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
smsSign: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入短信签名',
|
||||
type: 'string',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const toBool = (val: any): number =>
|
||||
val === true || val === 'true' || val === '1' || val === 1 ? 1 : 0;
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
// 数字/布尔值转换
|
||||
form.smsNoticeUser = toBool((values as any).smsNoticeUser);
|
||||
form.smsNoticeMerchant = toBool((values as any).smsNoticeMerchant);
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:label-col="styleResponsive ? { md: 3, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||
:wrapper-col="styleResponsive ? { md: 9, sm: 19, xs: 24 } : { flex: '1' }"
|
||||
>
|
||||
<a-form-item label="默认上传方式" name="uploadMethod">
|
||||
<a-radio-group v-model:value="form.uploadMethod">
|
||||
<a-radio-button value="file">本地</a-radio-button>
|
||||
<a-radio-button value="oss">阿里云 OSS</a-radio-button>
|
||||
<a-radio-button value="cos">腾讯云 COS</a-radio-button>
|
||||
<a-radio-button value="kodo">七牛云 Kodo</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<template v-if="form.uploadMethod === 'file'">
|
||||
<a-form-item label="文件域名" name="fileUrl">
|
||||
<a-input
|
||||
v-model:value="form.fileUrl"
|
||||
placeholder="请输入文件服务器域名,如 https://file.example.com"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="form.uploadMethod === 'oss'">
|
||||
<a-form-item label="存储空间名称" name="bucketName">
|
||||
<a-input v-model:value="form.bucketName" placeholder="Bucket Name" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Region 域名" name="bucketEndpoint">
|
||||
<a-input
|
||||
v-model:value="form.bucketEndpoint"
|
||||
placeholder="如 https://oss-cn-shenzhen.aliyuncs.com"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="AccessKeyId" name="accessKeyId">
|
||||
<a-input v-model:value="form.accessKeyId" placeholder="AccessKeyId" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="AccessKeySecret" name="accessKeySecret">
|
||||
<a-input-password
|
||||
v-model:value="form.accessKeySecret"
|
||||
placeholder="AccessKeySecret"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="空间域名" name="bucketDomain">
|
||||
<a-input
|
||||
v-model:value="form.bucketDomain"
|
||||
placeholder="如 https://your-bucket.oss-cn-shenzhen.aliyuncs.com"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请地址">
|
||||
<a href="https://oss.console.aliyun.com" target="_blank">https://oss.console.aliyun.com</a>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="form.uploadMethod === 'cos'">
|
||||
<a-form-item label="存储空间名称" name="bucketName">
|
||||
<a-input v-model:value="form.bucketName" placeholder="Bucket Name" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Region" name="bucketEndpoint">
|
||||
<a-input
|
||||
v-model:value="form.bucketEndpoint"
|
||||
placeholder="如 ap-guangzhou"
|
||||
allow-clear
|
||||
:maxlength="100"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="SecretId" name="accessKeyId">
|
||||
<a-input v-model:value="form.accessKeyId" placeholder="SecretId" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="SecretKey" name="accessKeySecret">
|
||||
<a-input-password
|
||||
v-model:value="form.accessKeySecret"
|
||||
placeholder="SecretKey"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="空间域名" name="bucketDomain">
|
||||
<a-input
|
||||
v-model:value="form.bucketDomain"
|
||||
placeholder="如 https://your-bucket.cos.ap-guangzhou.myqcloud.com"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请地址">
|
||||
<a href="https://console.cloud.tencent.com/cos" target="_blank">
|
||||
https://console.cloud.tencent.com/cos
|
||||
</a>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="form.uploadMethod === 'kodo'">
|
||||
<a-form-item label="存储空间名称" name="bucketName">
|
||||
<a-input v-model:value="form.bucketName" placeholder="Bucket Name" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="AccessKey" name="accessKeyId">
|
||||
<a-input v-model:value="form.accessKeyId" placeholder="AccessKey" allow-clear :maxlength="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="SecretKey" name="accessKeySecret">
|
||||
<a-input-password
|
||||
v-model:value="form.accessKeySecret"
|
||||
placeholder="SecretKey"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="空间域名" name="bucketDomain">
|
||||
<a-input
|
||||
v-model:value="form.bucketDomain"
|
||||
placeholder="如 https://your-bucket.qiniudn.com"
|
||||
allow-clear
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="申请地址">
|
||||
<a href="https://www.qiniu.com/products/kodo" target="_blank">
|
||||
https://www.qiniu.com/products/kodo
|
||||
</a>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
<a-form-item label="保存">
|
||||
<a-button type="primary" :loading="loading" @click="save">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { FormInstance } from 'ant-design-vue/es/form';
|
||||
import useFormData from '@/utils/use-form-data';
|
||||
import { batchSaveShopSetting, getShopSettingCategoryValues } from '@/api/shop/shopSetting';
|
||||
import type { ShopSetting } from '@/api/shop/shopSetting/model';
|
||||
|
||||
const category = 'upload';
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
const { form, assignFields } = useFormData<ShopSetting>({
|
||||
uploadMethod: 'oss',
|
||||
fileUrl: '',
|
||||
bucketName: '',
|
||||
bucketEndpoint: '',
|
||||
accessKeyId: '',
|
||||
accessKeySecret: '',
|
||||
bucketDomain: ''
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
uploadMethod: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择上传方式',
|
||||
type: 'string',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const toBool = (val: any): boolean =>
|
||||
val === true || val === 'true' || val === '1' || val === 1;
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
const values = await getShopSettingCategoryValues(category);
|
||||
if (values && Object.keys(values).length > 0) {
|
||||
assignFields(values);
|
||||
}
|
||||
} catch (e: any) {
|
||||
// 未配置时忽略
|
||||
}
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
batchSaveShopSetting(category, form as Record<string, unknown>)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class="ele-body ele-body-card">
|
||||
<a-card
|
||||
:bordered="false"
|
||||
:body-style="{ paddingTop: '0px', minHeight: '800px' }"
|
||||
>
|
||||
<a-tabs v-model:active-key="active">
|
||||
<a-tab-pane tab="基础设置" key="basic">
|
||||
<Basic />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="订单设置" key="order">
|
||||
<Order />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="积分设置" key="points">
|
||||
<Points />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="分销设置" key="dealer">
|
||||
<Dealer />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="支付设置" key="payment">
|
||||
<Payment />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="通知设置" key="notify">
|
||||
<Notify />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="上传设置" key="upload">
|
||||
<Upload />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="短信设置" key="sms">
|
||||
<Sms />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="小程序设置" key="miniprogram">
|
||||
<Miniprogram />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import Basic from './components/basic.vue';
|
||||
import Order from './components/order.vue';
|
||||
import Points from './components/points.vue';
|
||||
import Dealer from './components/dealer.vue';
|
||||
import Payment from './components/payment.vue';
|
||||
import Notify from './components/notify.vue';
|
||||
import Upload from './components/upload.vue';
|
||||
import Sms from './components/sms.vue';
|
||||
import Miniprogram from './components/miniprogram.vue';
|
||||
|
||||
const active = ref('basic');
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ShopSetting'
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user