Files
xingque/pages/merchant-staff-role/merchant-staff-role.js
XingQue c03d22776f backup: 紫色UI换肤前完整备份(当前橙色逍遥梦主题)
保留改造前全部页面样式与功能代码,便于回滚。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 01:59:42 +08:00

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();
}
},
});