feat: 商户账号管理
This commit is contained in:
parent
eefaf2140e
commit
83078e70c7
|
@ -0,0 +1,17 @@
|
||||||
|
import request from '@/utils/httpRequest'
|
||||||
|
|
||||||
|
export function inviteJoin(data) {
|
||||||
|
return request({
|
||||||
|
url: '/merchant-api/merchant/invite_join',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMerchantPermissions(data) {
|
||||||
|
return request({
|
||||||
|
url: '/merchant-api/subaccount/set-merchant-permissions',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,13 +1,326 @@
|
||||||
<template>
|
<template>
|
||||||
<div>商户账号管理</div>
|
<div class="app-container">
|
||||||
|
<el-form
|
||||||
|
ref="ruleFormRef"
|
||||||
|
:model="form"
|
||||||
|
label-position="left"
|
||||||
|
label-width="auto"
|
||||||
|
:rules="rules"
|
||||||
|
style="max-width: 600px"
|
||||||
|
>
|
||||||
|
<el-form-item v-if="!marketId && markets.length > 0" label="选择市场" prop="selectedMarketId">
|
||||||
|
<el-select v-model="form.selectedMarketId" placeholder="请选择市场" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="market in markets"
|
||||||
|
:key="market.marketId"
|
||||||
|
:label="market.marketName"
|
||||||
|
:value="market.marketId"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="操作类型" prop="operationType">
|
||||||
|
<el-select v-model="form.operationType" placeholder="请选择操作类型" style="width: 100%">
|
||||||
|
<el-option label="创建新商户" value="create"></el-option>
|
||||||
|
<el-option label="维护商户信息" value="update"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<template v-if="form.operationType === 'create'">
|
||||||
|
<el-form-item label="商户账号" prop="mobile">
|
||||||
|
<el-input v-model="form.mobile" placeholder="请输入商户账号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="password">
|
||||||
|
<el-input v-model="form.password" type="password" placeholder="请输入密码"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="form.operationType === 'update'">
|
||||||
|
<el-form-item label="选择商户账号" prop="accountId">
|
||||||
|
<el-select v-model="form.accountId" placeholder="请选择要更新的商户账号" @change="handleAccountChange" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in merchantAccountList"
|
||||||
|
:key="item.accountId"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.accountId"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="warning" @click="openResetPasswordDialog">重置密码</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-switch v-model="form.enable" active-text="启用" inactive-text="禁用"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form-item label="权限分配" prop="permissionCodes">
|
||||||
|
<el-tree
|
||||||
|
ref="permissionTree"
|
||||||
|
:data="permissionList"
|
||||||
|
show-checkbox
|
||||||
|
node-key="id"
|
||||||
|
:props="defaultProps"
|
||||||
|
@check="handleTreeCheck"
|
||||||
|
>
|
||||||
|
</el-tree>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="save">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
title="重置密码"
|
||||||
|
:visible.sync="resetPasswordDialogVisible"
|
||||||
|
width="30%"
|
||||||
|
@close="newPassword = ''"
|
||||||
|
>
|
||||||
|
<el-form label-width="80px">
|
||||||
|
<el-form-item label="新密码">
|
||||||
|
<el-input v-model="newPassword" type="password" placeholder="请输入新密码"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="resetPasswordDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="handleResetPassword">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {
|
||||||
|
getAvailablePermissions,
|
||||||
|
checkUsername,
|
||||||
|
resetPassword
|
||||||
|
} from '@/api/modules/subaccount' // Assuming some APIs can be reused
|
||||||
|
import { inviteJoin, setMerchantPermissions } from '@/api/modules/merchant' // New merchant API
|
||||||
|
import routerConfig from '@/router/full-routers'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
|
// Function to filter the full menu tree based on available permissions
|
||||||
|
const filterTreeByPerms = (tree, availablePerms) => {
|
||||||
|
if (!Array.isArray(tree)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return tree.reduce((acc, node) => {
|
||||||
|
const children = node.list && node.list.length > 0
|
||||||
|
? filterTreeByPerms(node.list, availablePerms)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (availablePerms.includes(node.perms) || children.length > 0) {
|
||||||
|
acc.push({
|
||||||
|
...node,
|
||||||
|
list: children,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to map the filtered tree to the format required by el-tree
|
||||||
|
const mapTreeForElTree = (tree) => {
|
||||||
|
return tree.map((item) => ({
|
||||||
|
id: item.perms,
|
||||||
|
label: item.name,
|
||||||
|
children: item.list && item.list.length > 0 ? mapTreeForElTree(item.list) : [],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MerchantAccount'
|
name: 'MerchantAccount',
|
||||||
|
data() {
|
||||||
|
const validateMobile = (rule, value, callback) => {
|
||||||
|
if (this.form.operationType !== 'create') {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error('请输入商户账号'));
|
||||||
|
}
|
||||||
|
checkUsername(value, this.form.selectedMarketId || this.marketId).then(res => {
|
||||||
|
if (res && res.data && res.data.data && res.data.data.available === true) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
callback(new Error('商户账号已被占用'));
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
callback(new Error('商户账号校验失败'));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
resetPasswordDialogVisible: false,
|
||||||
|
newPassword: '',
|
||||||
|
form: {
|
||||||
|
operationType: 'create',
|
||||||
|
mobile: '',
|
||||||
|
password: '',
|
||||||
|
permissionCodes: [],
|
||||||
|
accountId: null,
|
||||||
|
enable: true,
|
||||||
|
selectedMarketId: ''
|
||||||
|
},
|
||||||
|
merchantAccountList: [], // To be populated with merchant accounts
|
||||||
|
permissionList: [],
|
||||||
|
defaultProps: {
|
||||||
|
children: 'children',
|
||||||
|
label: 'label'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
operationType: [
|
||||||
|
{ required: true, message: "请选择操作类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
mobile: [
|
||||||
|
{ required: true, validator: validateMobile, trigger: "blur" },
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||||
|
],
|
||||||
|
permissionCodes: [
|
||||||
|
{ required: true, message: "请选择菜单权限", trigger: "change", type: 'array' },
|
||||||
|
],
|
||||||
|
accountId: [
|
||||||
|
{ required: true, message: "请选择要更新的商户账号", trigger: "change" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("userData", [
|
||||||
|
"isMerchant",
|
||||||
|
"marketList",
|
||||||
|
"storeList",
|
||||||
|
"marketId",
|
||||||
|
"shopId",
|
||||||
|
"markets"
|
||||||
|
])
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'form.operationType'(newType) {
|
||||||
|
this.form.mobile = '';
|
||||||
|
this.form.password = '';
|
||||||
|
this.form.permissionCodes = [];
|
||||||
|
this.form.accountId = null;
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.ruleFormRef.clearValidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.$refs.permissionTree) {
|
||||||
|
this.$refs.permissionTree.setCheckedKeys([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newType === 'update') {
|
||||||
|
// this.loadMerchantAccountList(); // To be implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getPermissions();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getPermissions() {
|
||||||
|
getAvailablePermissions().then((res) => {
|
||||||
|
const availablePerms = (res && res.data && Array.isArray(res.data.data)) ? res.data.data : [];
|
||||||
|
const menuList = (routerConfig && Array.isArray(routerConfig.menuList)) ? routerConfig.menuList : [];
|
||||||
|
const filteredTree = filterTreeByPerms(menuList, availablePerms);
|
||||||
|
this.permissionList = mapTreeForElTree(filteredTree);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openResetPasswordDialog() {
|
||||||
|
if (!this.form.accountId) {
|
||||||
|
this.$message.error('请先选择要更新的商户账号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resetPasswordDialogVisible = true;
|
||||||
|
},
|
||||||
|
handleResetPassword() {
|
||||||
|
if (!this.newPassword) {
|
||||||
|
this.$message.error('请输入新密码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resetPassword(this.form.accountId, this.newPassword, this.form.selectedMarketId || this.marketId).then(() => {
|
||||||
|
this.$message.success('密码重置成功');
|
||||||
|
this.resetPasswordDialogVisible = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleTreeCheck() {
|
||||||
|
this.form.permissionCodes = this.$refs.permissionTree.getCheckedKeys(true);
|
||||||
|
},
|
||||||
|
// To be implemented
|
||||||
|
// loadMerchantAccountList() {
|
||||||
|
// getMerchantAccountList().then(res => {
|
||||||
|
// this.merchantAccountList = res.data.data.data || [];
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
handleAccountChange(accountId) {
|
||||||
|
if (!accountId) return;
|
||||||
|
// getMerchantAccountDetail(accountId).then(res => {
|
||||||
|
// const accountDetails = res.data.data;
|
||||||
|
// this.form.permissionCodes = accountDetails.permissionCodes || [];
|
||||||
|
// this.form.enable = accountDetails.enabled;
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.$refs.permissionTree.setCheckedKeys(this.form.permissionCodes);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
this.$refs.ruleFormRef.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
const marketId = this.form.selectedMarketId || this.marketId;
|
||||||
|
if (!marketId) {
|
||||||
|
this.$message.error('请选择市场');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.form.operationType === 'create') {
|
||||||
|
const createData = {
|
||||||
|
marketId,
|
||||||
|
name: this.form.mobile,
|
||||||
|
mobile: this.form.mobile,
|
||||||
|
remark: '',
|
||||||
|
username: this.form.mobile,
|
||||||
|
password: this.form.password
|
||||||
|
};
|
||||||
|
inviteJoin(createData).then((res) => {
|
||||||
|
const merchantAccountId = res.data.data.merchantId; // Assuming this is the merchant ID
|
||||||
|
const permissionsData = {
|
||||||
|
merchantAccountId,
|
||||||
|
permissionCodes: this.form.permissionCodes,
|
||||||
|
marketId
|
||||||
|
};
|
||||||
|
setMerchantPermissions(permissionsData).then(() => {
|
||||||
|
this.$message.success('商户创建成功且权限已设置');
|
||||||
|
this.$refs.ruleFormRef.resetFields();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (this.form.operationType === 'update') {
|
||||||
|
if (!this.form.accountId) {
|
||||||
|
this.$message.error('请先选择要更新的商户账号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const updateData = {
|
||||||
|
subAccountId: this.form.accountId,
|
||||||
|
permissionCodes: this.form.permissionCodes,
|
||||||
|
enabled: this.form.enable,
|
||||||
|
marketId
|
||||||
|
};
|
||||||
|
// updateMerchantAccount(updateData).then(() => { // To be implemented
|
||||||
|
// this.$message.success('商户信息更新成功');
|
||||||
|
// this.$refs.ruleFormRef.resetFields();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
</style>
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -8,6 +8,17 @@
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
style="max-width: 600px"
|
style="max-width: 600px"
|
||||||
>
|
>
|
||||||
|
<el-form-item v-if="!marketId && markets.length > 0" label="选择市场" prop="selectedMarketId">
|
||||||
|
<el-select v-model="form.selectedMarketId" placeholder="请选择市场" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="market in markets"
|
||||||
|
:key="market.marketId"
|
||||||
|
:label="market.marketName"
|
||||||
|
:value="market.marketId"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="操作类型" prop="operationType">
|
<el-form-item label="操作类型" prop="operationType">
|
||||||
<el-select v-model="form.operationType" placeholder="请选择操作类型" style="width: 100%">
|
<el-select v-model="form.operationType" placeholder="请选择操作类型" style="width: 100%">
|
||||||
<el-option label="创建新账号" value="create"></el-option>
|
<el-option label="创建新账号" value="create"></el-option>
|
||||||
|
@ -100,6 +111,7 @@ import {
|
||||||
resetPassword
|
resetPassword
|
||||||
} from '@/api/modules/subaccount'
|
} from '@/api/modules/subaccount'
|
||||||
import routerConfig from '@/router/full-routers'
|
import routerConfig from '@/router/full-routers'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
// Function to filter the full menu tree based on available permissions
|
// Function to filter the full menu tree based on available permissions
|
||||||
const filterTreeByPerms = (tree, availablePerms) => {
|
const filterTreeByPerms = (tree, availablePerms) => {
|
||||||
|
@ -143,7 +155,7 @@ export default {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return callback(new Error('请输入账号'));
|
return callback(new Error('请输入账号'));
|
||||||
}
|
}
|
||||||
checkUsername(value).then(res => {
|
checkUsername(value, this.form.selectedMarketId || this.marketId).then(res => {
|
||||||
if (res && res.data && res.data.data && res.data.data.available === true) {
|
if (res && res.data && res.data.data && res.data.data.available === true) {
|
||||||
callback();
|
callback();
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,7 +178,8 @@ export default {
|
||||||
permissionCodes: [],
|
permissionCodes: [],
|
||||||
remark: '',
|
remark: '',
|
||||||
accountId: null,
|
accountId: null,
|
||||||
enable: true
|
enable: true,
|
||||||
|
selectedMarketId: ''
|
||||||
},
|
},
|
||||||
subAccountList: [],
|
subAccountList: [],
|
||||||
permissionList: [],
|
permissionList: [],
|
||||||
|
@ -199,6 +212,16 @@ export default {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState("userData", [
|
||||||
|
"isMerchant",
|
||||||
|
"marketList",
|
||||||
|
"storeList",
|
||||||
|
"marketId",
|
||||||
|
"shopId",
|
||||||
|
"markets"
|
||||||
|
])
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'form.operationType'(newType) {
|
'form.operationType'(newType) {
|
||||||
// Manually reset form fields to avoid resetting the operationType
|
// Manually reset form fields to avoid resetting the operationType
|
||||||
|
@ -249,7 +272,7 @@ export default {
|
||||||
this.$message.error('请输入新密码');
|
this.$message.error('请输入新密码');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetPassword(this.form.accountId, this.newPassword).then(() => {
|
resetPassword(this.form.accountId, this.newPassword, this.form.selectedMarketId || this.marketId).then(() => {
|
||||||
this.$message.success('密码重置成功');
|
this.$message.success('密码重置成功');
|
||||||
this.resetPasswordDialogVisible = false;
|
this.resetPasswordDialogVisible = false;
|
||||||
});
|
});
|
||||||
|
@ -259,13 +282,13 @@ export default {
|
||||||
this.form.permissionCodes = this.$refs.permissionTree.getCheckedKeys(true);
|
this.form.permissionCodes = this.$refs.permissionTree.getCheckedKeys(true);
|
||||||
},
|
},
|
||||||
loadSubAccountList() {
|
loadSubAccountList() {
|
||||||
getSubAccountList().then(res => {
|
getSubAccountList(this.form.selectedMarketId || this.marketId).then(res => {
|
||||||
this.subAccountList = res.data.data.data || [];
|
this.subAccountList = res.data.data.data || [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleAccountChange(accountId) {
|
handleAccountChange(accountId) {
|
||||||
if (!accountId) return;
|
if (!accountId) return;
|
||||||
getSubAccountDetail(accountId).then(res => {
|
getSubAccountDetail(accountId, this.form.selectedMarketId || this.marketId).then(res => {
|
||||||
const accountDetails = res.data.data;
|
const accountDetails = res.data.data;
|
||||||
this.form.name = accountDetails.name;
|
this.form.name = accountDetails.name;
|
||||||
this.form.mobile = accountDetails.mobile;
|
this.form.mobile = accountDetails.mobile;
|
||||||
|
@ -280,8 +303,14 @@ export default {
|
||||||
save() {
|
save() {
|
||||||
this.$refs.ruleFormRef.validate((valid) => {
|
this.$refs.ruleFormRef.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
const marketId = this.form.selectedMarketId || this.marketId;
|
||||||
|
if (!marketId) {
|
||||||
|
this.$message.error('请选择市场');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.form.operationType === 'create') {
|
if (this.form.operationType === 'create') {
|
||||||
const createData = { ...this.form };
|
const createData = { ...this.form, marketId };
|
||||||
if (createData.accountId === null) {
|
if (createData.accountId === null) {
|
||||||
delete createData.accountId;
|
delete createData.accountId;
|
||||||
}
|
}
|
||||||
|
@ -300,7 +329,8 @@ export default {
|
||||||
mobile: this.form.mobile,
|
mobile: this.form.mobile,
|
||||||
permissionCodes: this.form.permissionCodes,
|
permissionCodes: this.form.permissionCodes,
|
||||||
remark: this.form.remark,
|
remark: this.form.remark,
|
||||||
enabled: this.form.enable
|
enabled: this.form.enable,
|
||||||
|
marketId
|
||||||
};
|
};
|
||||||
updateSubAccount(updateData).then(() => {
|
updateSubAccount(updateData).then(() => {
|
||||||
this.$message.success('更新成功');
|
this.$message.success('更新成功');
|
||||||
|
|
Loading…
Reference in New Issue