feat: ai 联调
This commit is contained in:
@@ -8,6 +8,8 @@ import styles from './BlacklistAddModal.module.less';
|
|||||||
interface BlacklistAddModalProps {
|
interface BlacklistAddModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
submitting: boolean;
|
submitting: boolean;
|
||||||
|
/** 预设用户信息(从列表行「再次拉黑」带入时使用) */
|
||||||
|
presetUser?: { userId: string; phone?: string; nickname?: string };
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSubmit: (params: AiBlacklistAddParams) => void;
|
onSubmit: (params: AiBlacklistAddParams) => void;
|
||||||
}
|
}
|
||||||
@@ -27,12 +29,13 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
visible: { type: Boolean, default: false },
|
visible: { type: Boolean, default: false },
|
||||||
submitting: { type: Boolean, default: false },
|
submitting: { type: Boolean, default: false },
|
||||||
|
presetUser: { type: Object, default: undefined },
|
||||||
onClose: { type: Function, default: null },
|
onClose: { type: Function, default: null },
|
||||||
onSubmit: { type: Function, default: null },
|
onSubmit: { type: Function, default: null },
|
||||||
},
|
},
|
||||||
setup(props: BlacklistAddModalProps) {
|
setup(props: BlacklistAddModalProps) {
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
userId: undefined as number | undefined,
|
userId: undefined as string | undefined,
|
||||||
reason: '',
|
reason: '',
|
||||||
expireDate: null as Dayjs | null,
|
expireDate: null as Dayjs | null,
|
||||||
});
|
});
|
||||||
@@ -40,21 +43,33 @@ export default defineComponent({
|
|||||||
// 用户搜索
|
// 用户搜索
|
||||||
const userSearch = useUserSearch();
|
const userSearch = useUserSearch();
|
||||||
|
|
||||||
// 弹窗打开时重置表单
|
// 弹窗打开时重置表单 / 回填预设用户
|
||||||
|
// immediate: true 配合 destroyOnClose,组件重建后 visible 已为 true 时也能立即回填
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
form.userId = undefined;
|
|
||||||
form.reason = '';
|
form.reason = '';
|
||||||
form.expireDate = null;
|
form.expireDate = null;
|
||||||
userSearch.reset();
|
userSearch.reset();
|
||||||
|
if (props.presetUser) {
|
||||||
|
// 从列表行「再次拉黑」带入:回填 userId 并锁定
|
||||||
|
form.userId = props.presetUser.userId;
|
||||||
|
userSearch.setPresetUser({
|
||||||
|
userId: props.presetUser.userId,
|
||||||
|
phone: props.presetUser.phone,
|
||||||
|
nickname: props.presetUser.nickname,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
form.userId = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (!form.userId || form.userId <= 0) {
|
if (!form.userId) {
|
||||||
message.warning('请搜索并选择用户');
|
message.warning('请搜索并选择用户');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -99,14 +114,15 @@ export default defineComponent({
|
|||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
value={form.userId ? String(form.userId) : undefined}
|
value={form.userId ? String(form.userId) : undefined}
|
||||||
placeholder="输入手机号搜索用户"
|
placeholder="输入手机号或用户ID搜索"
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={userSearch.searching.value}
|
loading={userSearch.searching.value}
|
||||||
options={userSearch.options.value as any}
|
options={userSearch.options.value as any}
|
||||||
|
disabled={!!props.presetUser}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
onSearch={userSearch.onSearch}
|
onSearch={userSearch.onSearch}
|
||||||
onChange={(val: any) => {
|
onChange={(val: any) => {
|
||||||
form.userId = val ? Number(val) : undefined;
|
form.userId = val ? String(val) : undefined;
|
||||||
}}
|
}}
|
||||||
allowClear
|
allowClear
|
||||||
notFoundContent={
|
notFoundContent={
|
||||||
@@ -114,10 +130,12 @@ export default defineComponent({
|
|||||||
? '搜索中...'
|
? '搜索中...'
|
||||||
: userSearch.keyword.value
|
: userSearch.keyword.value
|
||||||
? '无匹配用户'
|
? '无匹配用户'
|
||||||
: '请输入手机号搜索'
|
: '请输入手机号或用户ID搜索'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div class={styles.tip}>搜索手机号选择需要拉黑的用户,展示手机号,传用户ID给后端</div>
|
<div class={styles.tip}>
|
||||||
|
搜索手机号或用户ID选择需要拉黑的用户,展示手机号,传用户ID给后端
|
||||||
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item label="拉黑原因" required>
|
<Form.Item label="拉黑原因" required>
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ export default defineComponent({
|
|||||||
pagination,
|
pagination,
|
||||||
addModalVisible,
|
addModalVisible,
|
||||||
submitting,
|
submitting,
|
||||||
|
presetUser,
|
||||||
handleSearch,
|
handleSearch,
|
||||||
handleReset,
|
handleReset,
|
||||||
handlePageChange,
|
handlePageChange,
|
||||||
openAddModal,
|
openAddModal,
|
||||||
|
openAddModalWithRecord,
|
||||||
closeAddModal,
|
closeAddModal,
|
||||||
handleSubmitAdd,
|
handleSubmitAdd,
|
||||||
handleRemove,
|
handleRemove,
|
||||||
@@ -49,14 +51,18 @@ export default defineComponent({
|
|||||||
|
|
||||||
/** 渲染操作列 */
|
/** 渲染操作列 */
|
||||||
const renderAction = (record: AiBlacklistVO) => {
|
const renderAction = (record: AiBlacklistVO) => {
|
||||||
if (record.status === 1) {
|
if (record.status == 1) {
|
||||||
return (
|
return (
|
||||||
<Button type="link" size="small" danger onClick={() => handleRemove(record)}>
|
<Button type="link" size="small" danger onClick={() => handleRemove(record)}>
|
||||||
解除拉黑
|
解除拉黑
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <span style={{ color: '#999' }}>-</span>;
|
return (
|
||||||
|
<Button type="link" size="small" danger onClick={() => openAddModalWithRecord(record)}>
|
||||||
|
再次拉黑
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 完整表格列 */
|
/** 完整表格列 */
|
||||||
@@ -65,7 +71,7 @@ export default defineComponent({
|
|||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: 100,
|
width: 120,
|
||||||
fixed: 'right' as const,
|
fixed: 'right' as const,
|
||||||
align: 'center' as const,
|
align: 'center' as const,
|
||||||
},
|
},
|
||||||
@@ -78,7 +84,7 @@ export default defineComponent({
|
|||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
value={filterForm.userId ? String(filterForm.userId) : undefined}
|
value={filterForm.userId ? String(filterForm.userId) : undefined}
|
||||||
placeholder="手机号搜索用户"
|
placeholder="手机号或用户ID搜索用户"
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={userSearch.searching.value}
|
loading={userSearch.searching.value}
|
||||||
options={userSearch.options.value as any}
|
options={userSearch.options.value as any}
|
||||||
@@ -93,7 +99,7 @@ export default defineComponent({
|
|||||||
? '搜索中...'
|
? '搜索中...'
|
||||||
: userSearch.keyword.value
|
: userSearch.keyword.value
|
||||||
? '无匹配用户'
|
? '无匹配用户'
|
||||||
: '输入手机号搜索'
|
: '输入手机号或用户ID搜索'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
@@ -152,6 +158,7 @@ export default defineComponent({
|
|||||||
<BlacklistAddModal
|
<BlacklistAddModal
|
||||||
visible={addModalVisible.value}
|
visible={addModalVisible.value}
|
||||||
submitting={submitting.value}
|
submitting={submitting.value}
|
||||||
|
presetUser={presetUser.value}
|
||||||
onClose={closeAddModal}
|
onClose={closeAddModal}
|
||||||
onSubmit={handleSubmitAdd}
|
onSubmit={handleSubmitAdd}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface PointsAdjustModalProps {
|
|||||||
visible: boolean;
|
visible: boolean;
|
||||||
submitting: boolean;
|
submitting: boolean;
|
||||||
/** 预设用户信息(从账户行点击调点时带入) */
|
/** 预设用户信息(从账户行点击调点时带入) */
|
||||||
presetUser?: { userId: number; phone?: string; nickname?: string };
|
presetUser?: { userId: string; phone?: string; nickname?: string };
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSubmit: (params: AiPointsAdjustParams) => void;
|
onSubmit: (params: AiPointsAdjustParams) => void;
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
setup(props: PointsAdjustModalProps) {
|
setup(props: PointsAdjustModalProps) {
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
userId: undefined as number | undefined,
|
userId: undefined as string | undefined,
|
||||||
points: undefined as number | undefined,
|
points: undefined as number | undefined,
|
||||||
type: 1 as number,
|
type: 1 as number,
|
||||||
descr: '',
|
descr: '',
|
||||||
@@ -60,7 +60,7 @@ export default defineComponent({
|
|||||||
}, [() => props.visible]);
|
}, [() => props.visible]);
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (!form.userId || form.userId <= 0) {
|
if (!form.userId) {
|
||||||
message.warning('请搜索并选择用户');
|
message.warning('请搜索并选择用户');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ export default defineComponent({
|
|||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
value={form.userId ? String(form.userId) : undefined}
|
value={form.userId ? String(form.userId) : undefined}
|
||||||
placeholder="输入手机号搜索用户"
|
placeholder="输入手机号或用户ID搜索"
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={userSearch.searching.value}
|
loading={userSearch.searching.value}
|
||||||
options={userSearch.options.value as any}
|
options={userSearch.options.value as any}
|
||||||
@@ -105,7 +105,7 @@ export default defineComponent({
|
|||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
onSearch={userSearch.onSearch}
|
onSearch={userSearch.onSearch}
|
||||||
onChange={(val: any) => {
|
onChange={(val: any) => {
|
||||||
form.userId = val ? Number(val) : undefined;
|
form.userId = val ? String(val) : undefined;
|
||||||
}}
|
}}
|
||||||
allowClear
|
allowClear
|
||||||
notFoundContent={
|
notFoundContent={
|
||||||
@@ -113,11 +113,11 @@ export default defineComponent({
|
|||||||
? '搜索中...'
|
? '搜索中...'
|
||||||
: userSearch.keyword.value
|
: userSearch.keyword.value
|
||||||
? '无匹配用户'
|
? '无匹配用户'
|
||||||
: '请输入手机号搜索'
|
: '请输入手机号或用户ID搜索'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div class={styles.tip}>
|
<div class={styles.tip}>
|
||||||
搜索手机号选择用户,展示手机号,传用户ID给后端;目标用户无账户时系统自动建户
|
搜索手机号或用户ID选择用户,展示手机号,传用户ID给后端;目标用户无账户时系统自动建户
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import PointsAdjustModal from './PointsAdjustModal';
|
|||||||
|
|
||||||
/** 用户搜索 Select 的 notFoundContent 公共渲染 */
|
/** 用户搜索 Select 的 notFoundContent 公共渲染 */
|
||||||
const renderNotFound = (searching: boolean, keyword: string) =>
|
const renderNotFound = (searching: boolean, keyword: string) =>
|
||||||
searching ? '搜索中...' : keyword ? '无匹配用户' : '输入手机号搜索';
|
searching ? '搜索中...' : keyword ? '无匹配用户' : '输入手机号或用户ID搜索';
|
||||||
|
|
||||||
/** 分页组件公共配置 */
|
/** 分页组件公共配置 */
|
||||||
const paginationProps = {
|
const paginationProps = {
|
||||||
@@ -169,7 +169,7 @@ export default defineComponent({
|
|||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
value={accountFilter.userId ? String(accountFilter.userId) : undefined}
|
value={accountFilter.userId ? String(accountFilter.userId) : undefined}
|
||||||
placeholder="手机号搜索用户"
|
placeholder="手机号或用户ID搜索用户"
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={accountSearch.searching.value}
|
loading={accountSearch.searching.value}
|
||||||
options={accountSearch.options.value as any}
|
options={accountSearch.options.value as any}
|
||||||
@@ -194,7 +194,7 @@ export default defineComponent({
|
|||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
value={txnFilter.userId ? String(txnFilter.userId) : undefined}
|
value={txnFilter.userId ? String(txnFilter.userId) : undefined}
|
||||||
placeholder="手机号搜索用户"
|
placeholder="手机号或用户ID搜索用户"
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={txnSearch.searching.value}
|
loading={txnSearch.searching.value}
|
||||||
options={txnSearch.options.value as any}
|
options={txnSearch.options.value as any}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { getUserList, type EventUserVO } from '@/pages/events/users/model/services';
|
import { getUserInfo, type UserInfoVO } from '../model/services';
|
||||||
|
|
||||||
export interface UserSearchOption {
|
export interface UserSearchOption {
|
||||||
/** userId 作为 value(传给后端) */
|
/** userId 作为 value(传给后端) */
|
||||||
@@ -7,17 +7,40 @@ export interface UserSearchOption {
|
|||||||
/** 展示文案:手机号(昵称) */
|
/** 展示文案:手机号(昵称) */
|
||||||
label: string;
|
label: string;
|
||||||
/** 原始用户数据 */
|
/** 原始用户数据 */
|
||||||
raw: EventUserVO;
|
raw: UserInfoVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PresetUserInfo {
|
export interface PresetUserInfo {
|
||||||
userId: number | string;
|
userId: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断输入是否为手机号:
|
||||||
|
* 中国大陆手机号 — 以 1 开头的 11 位数字
|
||||||
|
*/
|
||||||
|
const PHONE_REGEX = /^1[3-9]\d{9}$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断输入是否为雪花 ID:
|
||||||
|
* 雪花算法 ID 通常为 18~19 位纯数字
|
||||||
|
*/
|
||||||
|
const SNOWFLAKE_ID_REGEX = /^\d{17,20}$/;
|
||||||
|
|
||||||
|
/** 判断输入类型:手机号 / 雪花ID / 无效 */
|
||||||
|
export type SearchInputType = 'phone' | 'id' | 'unknown';
|
||||||
|
|
||||||
|
export function detectInputType(input: string): SearchInputType {
|
||||||
|
const trimmed = input.trim();
|
||||||
|
if (!trimmed) return 'unknown';
|
||||||
|
if (PHONE_REGEX.test(trimmed)) return 'phone';
|
||||||
|
if (SNOWFLAKE_ID_REGEX.test(trimmed)) return 'id';
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
export function useUserSearch(delay = 300) {
|
export function useUserSearch(delay = 300) {
|
||||||
/** 搜索关键字(内部管理,调用方无需关心) */
|
/** 搜索关键字 */
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
/** Select 选项列表 */
|
/** Select 选项列表 */
|
||||||
const options = ref<UserSearchOption[]>([]);
|
const options = ref<UserSearchOption[]>([]);
|
||||||
@@ -32,19 +55,27 @@ export function useUserSearch(delay = 300) {
|
|||||||
options.value = [];
|
options.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const inputType = detectInputType(trimmed);
|
||||||
|
if (inputType === 'unknown') {
|
||||||
|
options.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
searching.value = true;
|
searching.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await getUserList({
|
const params = inputType === 'phone' ? { phone: trimmed } : { id: trimmed };
|
||||||
page: '1',
|
|
||||||
limit: '20',
|
const res = await getUserInfo(params);
|
||||||
phone: trimmed,
|
if (res.code == 200 && res.data) {
|
||||||
});
|
const user = res.data;
|
||||||
if (res.code == 200 && res.data?.list) {
|
options.value = [
|
||||||
options.value = res.data.list.map((user) => ({
|
{
|
||||||
value: user.id,
|
value: user.id,
|
||||||
label: `${user.phone}${user.nickname ? `(${user.nickname})` : ''}`,
|
label: `${user.phone}${user.nickname ? `(${user.nickname})` : ''}`,
|
||||||
raw: user,
|
raw: user,
|
||||||
}));
|
},
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
options.value = [];
|
options.value = [];
|
||||||
}
|
}
|
||||||
@@ -66,9 +97,9 @@ export function useUserSearch(delay = 300) {
|
|||||||
timer = setTimeout(() => doSearch(val), delay);
|
timer = setTimeout(() => doSearch(val), delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Select onChange 回调:返回 userId(数字),清空时返回 undefined */
|
/** Select onChange 回调:返回 userId(字符串),清空时返回 undefined */
|
||||||
const onChange = (val: any): number | undefined => {
|
const onChange = (val: any): string | undefined => {
|
||||||
return val ? Number(val) : undefined;
|
return val ? String(val) : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 注入预设用户选项(从表格行点击带入时使用) */
|
/** 注入预设用户选项(从表格行点击带入时使用) */
|
||||||
@@ -82,15 +113,9 @@ export function useUserSearch(delay = 300) {
|
|||||||
label,
|
label,
|
||||||
raw: {
|
raw: {
|
||||||
id: String(user.userId),
|
id: String(user.userId),
|
||||||
nickname: user.nickname || '',
|
|
||||||
phone: user.phone || '',
|
phone: user.phone || '',
|
||||||
realName: '',
|
nickname: user.nickname || '',
|
||||||
idCard: '',
|
|
||||||
idCardImg: '',
|
|
||||||
idCardImgList: [],
|
|
||||||
gender: '',
|
|
||||||
status: '',
|
status: '',
|
||||||
createTime: '',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export interface AiModelDictResetParams {
|
|||||||
/** AI 积分账户 VO */
|
/** AI 积分账户 VO */
|
||||||
export interface AiPointsAccountVO {
|
export interface AiPointsAccountVO {
|
||||||
/** 用户 ID */
|
/** 用户 ID */
|
||||||
userId: number;
|
userId: string;
|
||||||
/** 昵称 */
|
/** 昵称 */
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
/** 手机号 */
|
/** 手机号 */
|
||||||
@@ -72,7 +72,7 @@ export interface AiPointsAccountVO {
|
|||||||
/** AI 积分流水 VO */
|
/** AI 积分流水 VO */
|
||||||
export interface AiPointsTxnVO {
|
export interface AiPointsTxnVO {
|
||||||
/** 用户 ID */
|
/** 用户 ID */
|
||||||
userId: number;
|
userId: string;
|
||||||
/** 昵称 */
|
/** 昵称 */
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
/** 手机号 */
|
/** 手机号 */
|
||||||
@@ -104,7 +104,7 @@ export interface AiPointsAccountQueryParams {
|
|||||||
page: number;
|
page: number;
|
||||||
size: number;
|
size: number;
|
||||||
/** 可选:用户 ID 筛选 */
|
/** 可选:用户 ID 筛选 */
|
||||||
userId?: number;
|
userId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 积分流水分页查询参数 */
|
/** 积分流水分页查询参数 */
|
||||||
@@ -112,7 +112,7 @@ export interface AiPointsTxnQueryParams {
|
|||||||
page: number;
|
page: number;
|
||||||
size: number;
|
size: number;
|
||||||
/** 可选:用户 ID 筛选 */
|
/** 可选:用户 ID 筛选 */
|
||||||
userId?: number;
|
userId?: string;
|
||||||
/** 可选:业务场景筛选 */
|
/** 可选:业务场景筛选 */
|
||||||
bizType?: string;
|
bizType?: string;
|
||||||
/** 可选:流水类型 1充值/2调账/3消费/4欠款 */
|
/** 可选:流水类型 1充值/2调账/3消费/4欠款 */
|
||||||
@@ -124,7 +124,7 @@ export interface AiPointsTxnQueryParams {
|
|||||||
/** 手工调点参数 */
|
/** 手工调点参数 */
|
||||||
export interface AiPointsAdjustParams {
|
export interface AiPointsAdjustParams {
|
||||||
/** 必填:用户 ID */
|
/** 必填:用户 ID */
|
||||||
userId: number;
|
userId: string;
|
||||||
/** 必填:积分数(非0;正=充/赠,负=扣) */
|
/** 必填:积分数(非0;正=充/赠,负=扣) */
|
||||||
points: number;
|
points: number;
|
||||||
/** 可选 1=充值/赠送 2=调账;缺省按正负推导 */
|
/** 可选 1=充值/赠送 2=调账;缺省按正负推导 */
|
||||||
@@ -135,9 +135,9 @@ export interface AiPointsAdjustParams {
|
|||||||
|
|
||||||
/** AI 黑名单 VO */
|
/** AI 黑名单 VO */
|
||||||
export interface AiBlacklistVO {
|
export interface AiBlacklistVO {
|
||||||
id: number;
|
id: string;
|
||||||
/** 用户 ID */
|
/** 用户 ID */
|
||||||
userId: number;
|
userId: string;
|
||||||
/** 昵称 */
|
/** 昵称 */
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
/** 手机号 */
|
/** 手机号 */
|
||||||
@@ -149,7 +149,7 @@ export interface AiBlacklistVO {
|
|||||||
/** 到期时间(null=永久;yyyy-MM-dd HH:mm:ss) */
|
/** 到期时间(null=永久;yyyy-MM-dd HH:mm:ss) */
|
||||||
expireDate: string | null;
|
expireDate: string | null;
|
||||||
/** 操作人 ID */
|
/** 操作人 ID */
|
||||||
operatorId: number;
|
operatorId: string;
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
createDate: string;
|
createDate: string;
|
||||||
/** 更新时间 */
|
/** 更新时间 */
|
||||||
@@ -161,7 +161,7 @@ export interface AiBlacklistQueryParams {
|
|||||||
page: number;
|
page: number;
|
||||||
size: number;
|
size: number;
|
||||||
/** 可选:用户 ID 筛选 */
|
/** 可选:用户 ID 筛选 */
|
||||||
userId?: number;
|
userId?: string;
|
||||||
/** 可选:状态筛选 1=拉黑中 0=已解除 */
|
/** 可选:状态筛选 1=拉黑中 0=已解除 */
|
||||||
status?: number;
|
status?: number;
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ export interface AiBlacklistQueryParams {
|
|||||||
/** 拉黑参数 */
|
/** 拉黑参数 */
|
||||||
export interface AiBlacklistAddParams {
|
export interface AiBlacklistAddParams {
|
||||||
/** 必填:用户 ID */
|
/** 必填:用户 ID */
|
||||||
userId: number;
|
userId: string;
|
||||||
/** 必填:拉黑原因 */
|
/** 必填:拉黑原因 */
|
||||||
reason: string;
|
reason: string;
|
||||||
/** 可选:到期时间(yyyy-MM-dd[ HH:mm:ss];空=永久) */
|
/** 可选:到期时间(yyyy-MM-dd[ HH:mm:ss];空=永久) */
|
||||||
@@ -178,7 +178,7 @@ export interface AiBlacklistAddParams {
|
|||||||
|
|
||||||
/** 解除拉黑参数 */
|
/** 解除拉黑参数 */
|
||||||
export interface AiBlacklistRemoveParams {
|
export interface AiBlacklistRemoveParams {
|
||||||
userId: number;
|
userId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 分页数据 */
|
/** 分页数据 */
|
||||||
@@ -311,6 +311,7 @@ const DICT_DATA_SAVE = '/admin/manager/dict/data/save';
|
|||||||
const DICT_DATA_DELETE = '/admin/manager/dict/data/delete';
|
const DICT_DATA_DELETE = '/admin/manager/dict/data/delete';
|
||||||
const AI_BILLING_REPORT = '/admin/manager/ai/billing/report';
|
const AI_BILLING_REPORT = '/admin/manager/ai/billing/report';
|
||||||
const AI_FREEFORM_REPORT = '/admin/manager/ai/freeform/report';
|
const AI_FREEFORM_REPORT = '/admin/manager/ai/freeform/report';
|
||||||
|
const USER_INFO = '/admin/manager/user/info';
|
||||||
|
|
||||||
/** 单价字典类型标识 */
|
/** 单价字典类型标识 */
|
||||||
export const AI_BILLING_PRICE_DICT_TYPE = 'ai_billing_price';
|
export const AI_BILLING_PRICE_DICT_TYPE = 'ai_billing_price';
|
||||||
@@ -414,3 +415,25 @@ export function getAiFreeformReport(
|
|||||||
): Promise<ApiResult<AiFreeformReportVO[]>> {
|
): Promise<ApiResult<AiFreeformReportVO[]>> {
|
||||||
return get(AI_FREEFORM_REPORT, params as Record<string, unknown>);
|
return get(AI_FREEFORM_REPORT, params as Record<string, unknown>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 用户信息查询参数(GET /admin/manager/user/info) */
|
||||||
|
export interface UserInfoQueryParams {
|
||||||
|
/** 雪花 ID */
|
||||||
|
id?: string;
|
||||||
|
/** 手机号 */
|
||||||
|
phone?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户信息返回 */
|
||||||
|
export interface UserInfoVO {
|
||||||
|
id: string;
|
||||||
|
phone: string;
|
||||||
|
nickname: string;
|
||||||
|
status: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按 id 或手机号查询单个用户信息 */
|
||||||
|
export function getUserInfo(params: UserInfoQueryParams): Promise<ApiResult<UserInfoVO>> {
|
||||||
|
return get(USER_INFO, params as Record<string, unknown>);
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import {
|
|||||||
*/
|
*/
|
||||||
export function useBlacklistModel() {
|
export function useBlacklistModel() {
|
||||||
const filterForm = reactive({
|
const filterForm = reactive({
|
||||||
userId: '' as string | number,
|
userId: '' as string,
|
||||||
status: '' as '' | number,
|
status: '' as '' | number,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,8 +39,8 @@ export function useBlacklistModel() {
|
|||||||
size: (pagination as any).pageSize.value,
|
size: (pagination as any).pageSize.value,
|
||||||
};
|
};
|
||||||
const uid = filterForm.userId;
|
const uid = filterForm.userId;
|
||||||
if (uid !== '' && uid != null && !Number.isNaN(Number(uid))) {
|
if (uid) {
|
||||||
params.userId = Number(uid);
|
params.userId = String(uid);
|
||||||
}
|
}
|
||||||
if (filterForm.status !== '') {
|
if (filterForm.status !== '') {
|
||||||
params.status = Number(filterForm.status);
|
params.status = Number(filterForm.status);
|
||||||
@@ -68,6 +68,10 @@ export function useBlacklistModel() {
|
|||||||
|
|
||||||
const addModalVisible = ref(false);
|
const addModalVisible = ref(false);
|
||||||
const submitting = ref(false);
|
const submitting = ref(false);
|
||||||
|
/** 预设用户信息(从列表「再次拉黑」带入) */
|
||||||
|
const presetUser = ref<{ userId: string; phone?: string; nickname?: string } | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
/** 搜索 */
|
/** 搜索 */
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
@@ -94,12 +98,24 @@ export function useBlacklistModel() {
|
|||||||
|
|
||||||
/** 打开拉黑弹窗 */
|
/** 打开拉黑弹窗 */
|
||||||
const openAddModal = () => {
|
const openAddModal = () => {
|
||||||
|
presetUser.value = undefined;
|
||||||
|
addModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 打开拉黑弹窗(带预设用户信息,用于「再次拉黑」) */
|
||||||
|
const openAddModalWithRecord = (record: AiBlacklistVO) => {
|
||||||
|
presetUser.value = {
|
||||||
|
userId: record.userId,
|
||||||
|
phone: record.phone,
|
||||||
|
nickname: record.nickname,
|
||||||
|
};
|
||||||
addModalVisible.value = true;
|
addModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 关闭拉黑弹窗 */
|
/** 关闭拉黑弹窗 */
|
||||||
const closeAddModal = () => {
|
const closeAddModal = () => {
|
||||||
addModalVisible.value = false;
|
addModalVisible.value = false;
|
||||||
|
presetUser.value = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 提交拉黑 */
|
/** 提交拉黑 */
|
||||||
@@ -132,7 +148,7 @@ export function useBlacklistModel() {
|
|||||||
try {
|
try {
|
||||||
const res = await removeAiBlacklist({ userId: record.userId });
|
const res = await removeAiBlacklist({ userId: record.userId });
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
message.success(res.msg || '已解除拉黑');
|
message.success('已解除拉黑');
|
||||||
fetchList();
|
fetchList();
|
||||||
} else {
|
} else {
|
||||||
message.error(res.msg || '解除失败');
|
message.error(res.msg || '解除失败');
|
||||||
@@ -151,10 +167,12 @@ export function useBlacklistModel() {
|
|||||||
pagination,
|
pagination,
|
||||||
addModalVisible,
|
addModalVisible,
|
||||||
submitting,
|
submitting,
|
||||||
|
presetUser,
|
||||||
handleSearch,
|
handleSearch,
|
||||||
handleReset,
|
handleReset,
|
||||||
handlePageChange,
|
handlePageChange,
|
||||||
openAddModal,
|
openAddModal,
|
||||||
|
openAddModalWithRecord,
|
||||||
closeAddModal,
|
closeAddModal,
|
||||||
handleSubmitAdd,
|
handleSubmitAdd,
|
||||||
handleRemove,
|
handleRemove,
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ export function usePointsModel() {
|
|||||||
const subView = ref<'account' | 'txn'>('account');
|
const subView = ref<'account' | 'txn'>('account');
|
||||||
|
|
||||||
const accountFilter = reactive({
|
const accountFilter = reactive({
|
||||||
userId: '' as string | number,
|
userId: '' as string,
|
||||||
});
|
});
|
||||||
|
|
||||||
const txnFilter = reactive({
|
const txnFilter = reactive({
|
||||||
userId: '' as string | number,
|
userId: '' as string,
|
||||||
bizType: '' as string,
|
bizType: '' as string,
|
||||||
type: '' as '' | number,
|
type: '' as '' | number,
|
||||||
date: '' as string,
|
date: '' as string,
|
||||||
@@ -50,8 +50,8 @@ export function usePointsModel() {
|
|||||||
size: (accountPagination as any).pageSize.value,
|
size: (accountPagination as any).pageSize.value,
|
||||||
};
|
};
|
||||||
const uid = accountFilter.userId;
|
const uid = accountFilter.userId;
|
||||||
if (uid !== '' && uid != null && !Number.isNaN(Number(uid))) {
|
if (uid) {
|
||||||
params.userId = Number(uid);
|
params.userId = String(uid);
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
};
|
};
|
||||||
@@ -62,8 +62,8 @@ export function usePointsModel() {
|
|||||||
size: (txnPagination as any).pageSize.value,
|
size: (txnPagination as any).pageSize.value,
|
||||||
};
|
};
|
||||||
const uid = txnFilter.userId;
|
const uid = txnFilter.userId;
|
||||||
if (uid !== '' && uid != null && !Number.isNaN(Number(uid))) {
|
if (uid) {
|
||||||
params.userId = Number(uid);
|
params.userId = String(uid);
|
||||||
}
|
}
|
||||||
if (txnFilter.bizType) {
|
if (txnFilter.bizType) {
|
||||||
params.bizType = txnFilter.bizType;
|
params.bizType = txnFilter.bizType;
|
||||||
@@ -116,7 +116,7 @@ export function usePointsModel() {
|
|||||||
const adjustModalVisible = ref(false);
|
const adjustModalVisible = ref(false);
|
||||||
const adjusting = ref(false);
|
const adjusting = ref(false);
|
||||||
/** 调点弹窗预设用户信息(从账户行点击「调点」时带入) */
|
/** 调点弹窗预设用户信息(从账户行点击「调点」时带入) */
|
||||||
const presetUser = ref<{ userId: number; phone?: string; nickname?: string } | undefined>(
|
const presetUser = ref<{ userId: string; phone?: string; nickname?: string } | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ export function usePointsModel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 打开调点弹窗(可预设用户信息) */
|
/** 打开调点弹窗(可预设用户信息) */
|
||||||
const openAdjustModal = (user?: { userId: number; phone?: string; nickname?: string }) => {
|
const openAdjustModal = (user?: { userId: string; phone?: string; nickname?: string }) => {
|
||||||
presetUser.value = user;
|
presetUser.value = user;
|
||||||
adjustModalVisible.value = true;
|
adjustModalVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user