237 lines
7.2 KiB
JavaScript
237 lines
7.2 KiB
JavaScript
/** 商家老板:角色与权限管理 */
|
|
import request from '../../utils/request.js';
|
|
import { STAFF_API, isStaffMode, isMerchantOwnerOnly } from '../../utils/staff-api.js';
|
|
|
|
/** 与后端 constants.PERMISSION_DEFINITIONS 一致,接口为空时前端兜底 */
|
|
const FALLBACK_PERMISSIONS = [
|
|
{ perm_code: 'staff_manage', perm_name: '子客服管理' },
|
|
{ perm_code: 'role_manage', perm_name: '角色管理' },
|
|
{ perm_code: 'wallet_allocate', perm_name: '划额度' },
|
|
{ perm_code: 'wallet_revoke', perm_name: '收回额度' },
|
|
{ perm_code: 'wallet_view', perm_name: '查看额度' },
|
|
{ perm_code: 'finance_view', perm_name: '查看商家余额' },
|
|
{ perm_code: 'order_dispatch', perm_name: '派单发单' },
|
|
{ perm_code: 'order_view_all', perm_name: '查看全部订单' },
|
|
{ perm_code: 'order_view_self', perm_name: '只看自己派的单' },
|
|
{ perm_code: 'order_detail', perm_name: '订单详情' },
|
|
{ perm_code: 'order_settle', perm_name: '结单' },
|
|
{ perm_code: 'order_refund_apply', perm_name: '申请退款' },
|
|
{ perm_code: 'order_cancel', perm_name: '撤销订单' },
|
|
{ perm_code: 'order_change_player', perm_name: '换打手' },
|
|
{ perm_code: 'penalty_apply', perm_name: '申请罚单' },
|
|
{ perm_code: 'penalty_manage', perm_name: '改撤罚单' },
|
|
{ perm_code: 'penalty_view', perm_name: '查看罚单' },
|
|
{ perm_code: 'staff_disable', perm_name: '封禁解封客服' },
|
|
{ perm_code: 'template_manage', perm_name: '派单模板' },
|
|
{ perm_code: 'audit_view', perm_name: '操作日志' },
|
|
{ perm_code: 'rank_view', perm_name: '客服排行榜' },
|
|
{ perm_code: 'im_chat', perm_name: '订单IM' },
|
|
{ perm_code: 'stats_view', perm_name: '统计数据' },
|
|
];
|
|
|
|
Page({
|
|
data: {
|
|
statusBar: 20,
|
|
permScrollHeight: 360,
|
|
loading: false,
|
|
roles: [],
|
|
rawPermissions: [],
|
|
permissionOptions: [],
|
|
selectedPerms: [],
|
|
showEditPanel: false,
|
|
showCreatePanel: false,
|
|
editingRoleId: null,
|
|
editingRoleName: '',
|
|
newRoleName: '',
|
|
},
|
|
|
|
onLoad() {
|
|
const sys = wx.getSystemInfoSync();
|
|
const h = sys.windowHeight || 667;
|
|
this.setData({
|
|
statusBar: sys.statusBarHeight || 20,
|
|
permScrollHeight: Math.floor(h * 0.45),
|
|
});
|
|
if (!this.ensureOwnerAccess()) return;
|
|
this.loadRoles();
|
|
},
|
|
|
|
onShow() {
|
|
if (!isMerchantOwnerOnly()) return;
|
|
if (!this.data.showEditPanel && !this.data.showCreatePanel) {
|
|
this.loadRoles();
|
|
}
|
|
},
|
|
|
|
ensureOwnerAccess() {
|
|
if (isStaffMode() || Number(wx.getStorageSync('shangjiastatus')) !== 1) {
|
|
wx.showToast({ title: '仅商家老板可管理角色权限', icon: 'none' });
|
|
setTimeout(() => wx.navigateBack(), 1200);
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
/** allPerms: [{perm_code, perm_name}] selectedCodes: ['order_dispatch', ...] */
|
|
buildPermOptions(allPerms, selectedCodes) {
|
|
const list = (allPerms && allPerms.length) ? allPerms : FALLBACK_PERMISSIONS;
|
|
const set = new Set(selectedCodes || []);
|
|
return list.map((p) => {
|
|
const code = p.perm_code || p;
|
|
const name = p.perm_name || code;
|
|
return {
|
|
perm_code: code,
|
|
perm_name: name,
|
|
checked: set.has(code),
|
|
};
|
|
});
|
|
},
|
|
|
|
normalizeRoles(list) {
|
|
return (list || []).map((r) => ({
|
|
...r,
|
|
permCount: (r.permissions && r.permissions.length) || 0,
|
|
}));
|
|
},
|
|
|
|
resolveAllPermissions(apiList) {
|
|
if (apiList && apiList.length) return apiList;
|
|
return FALLBACK_PERMISSIONS;
|
|
},
|
|
|
|
async loadRoles() {
|
|
this.setData({ loading: true });
|
|
try {
|
|
const res = await request({ url: STAFF_API.roleList, method: 'POST' });
|
|
if (res.data && res.data.code === 0) {
|
|
const d = res.data.data || {};
|
|
const rawPermissions = this.resolveAllPermissions(d.all_permissions);
|
|
this.setData({
|
|
roles: this.normalizeRoles(d.roles),
|
|
rawPermissions,
|
|
});
|
|
return rawPermissions;
|
|
}
|
|
wx.showToast({ title: (res.data && res.data.msg) || '加载失败', icon: 'none' });
|
|
} catch (e) {
|
|
wx.showToast({ title: '加载失败', icon: 'none' });
|
|
} finally {
|
|
this.setData({ loading: false });
|
|
}
|
|
const fallback = FALLBACK_PERMISSIONS;
|
|
this.setData({ rawPermissions: fallback });
|
|
return fallback;
|
|
},
|
|
|
|
goBack() { wx.navigateBack(); },
|
|
|
|
openCreate() {
|
|
const raw = this.data.rawPermissions.length
|
|
? this.data.rawPermissions
|
|
: FALLBACK_PERMISSIONS;
|
|
this.setData({
|
|
showCreatePanel: true,
|
|
showEditPanel: false,
|
|
newRoleName: '',
|
|
selectedPerms: [],
|
|
permissionOptions: this.buildPermOptions(raw, []),
|
|
});
|
|
},
|
|
|
|
closeCreate() {
|
|
this.setData({ showCreatePanel: false, permissionOptions: [], selectedPerms: [] });
|
|
},
|
|
|
|
onNameInput(e) {
|
|
this.setData({ newRoleName: e.detail.value });
|
|
},
|
|
|
|
togglePermItem(e) {
|
|
const code = e.currentTarget.dataset.code;
|
|
if (!code) return;
|
|
const opts = (this.data.permissionOptions || []).map((p) => (
|
|
p.perm_code === code ? { ...p, checked: !p.checked } : p
|
|
));
|
|
this.setData({
|
|
permissionOptions: opts,
|
|
selectedPerms: opts.filter((x) => x.checked).map((x) => x.perm_code),
|
|
});
|
|
},
|
|
|
|
async editRole(e) {
|
|
const id = e.currentTarget.dataset.id;
|
|
let role = this.data.roles.find((r) => String(r.id) === String(id));
|
|
if (!role) return;
|
|
|
|
let rawPermissions = this.data.rawPermissions;
|
|
if (!rawPermissions.length) {
|
|
rawPermissions = await this.loadRoles();
|
|
role = this.data.roles.find((r) => String(r.id) === String(id));
|
|
if (!role) return;
|
|
}
|
|
|
|
const perms = role.permissions || [];
|
|
this.setData({
|
|
showEditPanel: true,
|
|
showCreatePanel: false,
|
|
editingRoleId: role.id,
|
|
editingRoleName: role.role_name || '',
|
|
selectedPerms: [...perms],
|
|
permissionOptions: this.buildPermOptions(rawPermissions, perms),
|
|
});
|
|
},
|
|
|
|
closeEdit() {
|
|
this.setData({
|
|
showEditPanel: false,
|
|
editingRoleId: null,
|
|
editingRoleName: '',
|
|
selectedPerms: [],
|
|
permissionOptions: [],
|
|
});
|
|
},
|
|
|
|
async saveRolePerms() {
|
|
const { editingRoleId, selectedPerms } = this.data;
|
|
if (!editingRoleId) return;
|
|
wx.showLoading({ title: '保存中' });
|
|
try {
|
|
const res = await request({
|
|
url: STAFF_API.roleSetPerms,
|
|
method: 'POST',
|
|
data: { role_id: editingRoleId, permissions: selectedPerms },
|
|
});
|
|
wx.showToast({ title: (res.data && res.data.msg) || '已保存', icon: 'none' });
|
|
if (res.data && res.data.code === 0) {
|
|
this.closeEdit();
|
|
this.loadRoles();
|
|
}
|
|
} finally {
|
|
wx.hideLoading();
|
|
}
|
|
},
|
|
|
|
async createRole() {
|
|
const name = (this.data.newRoleName || '').trim();
|
|
if (!name) {
|
|
wx.showToast({ title: '请输入角色名', icon: 'none' });
|
|
return;
|
|
}
|
|
wx.showLoading({ title: '创建中' });
|
|
try {
|
|
const res = await request({
|
|
url: STAFF_API.roleCreate,
|
|
method: 'POST',
|
|
data: { role_name: name, permissions: this.data.selectedPerms },
|
|
});
|
|
wx.showToast({ title: (res.data && res.data.msg) || '完成', icon: 'none' });
|
|
if (res.data && res.data.code === 0) {
|
|
this.closeCreate();
|
|
this.loadRoles();
|
|
}
|
|
} finally {
|
|
wx.hideLoading();
|
|
}
|
|
},
|
|
});
|