1. extract isTenantBound utility from user store logic 2. add disabled state to tenant select components across all IM pages 3. update policy tenant options logic to hide global option for bound tenants 4. add backend scope validation for IM admin operations
193 lines
4.7 KiB
TypeScript
193 lines
4.7 KiB
TypeScript
import { computed, ref } from 'vue';
|
|
import { cloneDeep } from 'lodash-es';
|
|
import { FormSchema } from '@/components/Form';
|
|
import { defRangeShortcuts } from '@/utils/dateUtil';
|
|
import { useDictStore } from '@/store/modules/dict';
|
|
import { isTenantBound, loadImTenantOptions } from '@/views/imTenantOptions';
|
|
|
|
const dict = useDictStore();
|
|
|
|
export const tenantOptions = ref<any[]>([]);
|
|
|
|
export const workOrderTypeOptions = [
|
|
{ label: '举报', value: 'abuse' },
|
|
{ label: '反馈', value: 'feedback' },
|
|
];
|
|
|
|
// 目标类型映射
|
|
const targetTypeMap: Record<string, string> = {
|
|
user: '用户',
|
|
group: '群聊',
|
|
message: '消息',
|
|
};
|
|
|
|
// 分类映射:举报按 reason_code,反馈按 category
|
|
const abuseCategoryMap: Record<string, string> = {
|
|
spam: '垃圾广告',
|
|
harassment: '骚扰辱骂',
|
|
illegal: '违法违规',
|
|
fraud: '诈骗欺诈',
|
|
other: '其他',
|
|
};
|
|
const feedbackCategoryMap: Record<string, string> = {
|
|
bug: '功能异常',
|
|
suggestion: '功能建议',
|
|
complaint: '投诉',
|
|
other: '其他',
|
|
};
|
|
|
|
export function categoryLabelOf(type: string, category: string) {
|
|
const map = type === 'abuse' ? abuseCategoryMap : feedbackCategoryMap;
|
|
return map[category] || category || '-';
|
|
}
|
|
|
|
export function targetTypeLabel(targetType: string) {
|
|
return targetTypeMap[targetType] || (targetType || '-');
|
|
}
|
|
|
|
export class State {
|
|
public tenantId = 0;
|
|
public tenantName = '';
|
|
public type = 'abuse';
|
|
public id = 0;
|
|
public orderId = '';
|
|
public userId = 0;
|
|
public targetType = '';
|
|
public targetSummary = '';
|
|
public category = '';
|
|
public content = '';
|
|
public status = '';
|
|
public description = '';
|
|
public contact = '';
|
|
public evidenceJson = '';
|
|
public snapshotJson = '';
|
|
public clientContextJson = '';
|
|
public includeDiagnostics = 0;
|
|
public idempotencyKey = '';
|
|
public createdAt = '';
|
|
public updatedAt = '';
|
|
|
|
constructor(state?: Partial<State>) {
|
|
if (state) Object.assign(this, state);
|
|
}
|
|
}
|
|
|
|
export function newState(state: State | Record<string, any> | null): State {
|
|
if (state !== null) {
|
|
if (state instanceof State) return cloneDeep(state);
|
|
return new State(state);
|
|
}
|
|
return new State();
|
|
}
|
|
|
|
export const schemas = ref<FormSchema[]>([
|
|
{
|
|
field: 'tenantId',
|
|
component: 'NSelect',
|
|
label: '商户',
|
|
componentProps: {
|
|
clearable: false,
|
|
options: computed(() => tenantOptions.value),
|
|
disabled: isTenantBound(),
|
|
placeholder: '请选择商户',
|
|
},
|
|
},
|
|
{
|
|
field: 'type',
|
|
component: 'NSelect',
|
|
label: '类型',
|
|
defaultValue: 'abuse',
|
|
componentProps: {
|
|
clearable: false,
|
|
options: workOrderTypeOptions,
|
|
placeholder: '请选择类型',
|
|
},
|
|
},
|
|
{
|
|
field: 'userId',
|
|
component: 'NInput',
|
|
label: '提交人ID',
|
|
componentProps: { placeholder: '请输入提交人ID' },
|
|
},
|
|
{
|
|
field: 'status',
|
|
component: 'NSelect',
|
|
label: '状态',
|
|
componentProps: {
|
|
clearable: true,
|
|
options: dict.getOption('ImWorkOrderStatusOptions'),
|
|
placeholder: '请选择状态',
|
|
},
|
|
},
|
|
{
|
|
field: 'keyword',
|
|
component: 'NInput',
|
|
label: '关键词',
|
|
componentProps: { placeholder: '请输入内容关键词' },
|
|
},
|
|
{
|
|
field: 'createdAt',
|
|
component: 'NDatePicker',
|
|
label: '创建时间',
|
|
componentProps: {
|
|
type: 'datetimerange',
|
|
clearable: true,
|
|
shortcuts: defRangeShortcuts(),
|
|
},
|
|
},
|
|
]);
|
|
|
|
export const columns = [
|
|
{
|
|
title: '类型',
|
|
key: 'type',
|
|
align: 'left',
|
|
width: 90,
|
|
render(row: State) {
|
|
return row.type === 'abuse' ? '举报' : '反馈';
|
|
},
|
|
},
|
|
{ title: 'ID', key: 'id', align: 'left', width: 80 },
|
|
{ title: '工单ID', key: 'orderId', align: 'left', width: 180 },
|
|
{ title: '提交人ID', key: 'userId', align: 'left', width: 120 },
|
|
{
|
|
title: '目标类型',
|
|
key: 'targetType',
|
|
align: 'left',
|
|
width: 110,
|
|
render(row: State) {
|
|
return targetTypeLabel(row.targetType);
|
|
},
|
|
},
|
|
{ title: '目标摘要', key: 'targetSummary', align: 'left', width: 220 },
|
|
{
|
|
title: '分类',
|
|
key: 'category',
|
|
align: 'left',
|
|
width: 130,
|
|
render(row: State) {
|
|
return categoryLabelOf(row.type, row.category);
|
|
},
|
|
},
|
|
{ title: '内容', key: 'content', align: 'left', width: 260 },
|
|
{
|
|
title: '状态',
|
|
key: 'status',
|
|
align: 'left',
|
|
width: 110,
|
|
render(row: State) {
|
|
return dict.getLabel('ImWorkOrderStatusOptions', row.status);
|
|
},
|
|
},
|
|
{ title: '创建时间', key: 'createdAt', align: 'left', width: 180 },
|
|
{ title: '修改时间', key: 'updatedAt', align: 'left', width: 180 },
|
|
];
|
|
|
|
export function loadOptions() {
|
|
dict.loadOptions(['ImWorkOrderStatusOptions']);
|
|
}
|
|
|
|
export async function loadTenantOptions() {
|
|
return loadImTenantOptions(tenantOptions, { page: 1, perPage: 20 });
|
|
}
|