fix(api): 增强创建者选择逻辑以支持手机号自动匹配

- 更新创建者查询逻辑,新增手机号字段以便于选择
- 修改前端逻辑,支持通过 URL 中的手机号自动选中创建者
- 优化创建者选择组件,确保在禁用状态下仍能正确显示选项
- 增强日志记录,提供手机号匹配的调试信息,提升用户体验
This commit is contained in:
zhouyonggao 2025-12-19 17:09:39 +08:00
parent 6df550beb9
commit c5f6f6c6e9
4 changed files with 52 additions and 44 deletions

View File

@ -33,13 +33,13 @@ func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
limit = n
}
}
// 查询 admin_user 表的 id 和 real_name
sqlStr := "SELECT id, COALESCE(real_name, '') AS name FROM `admin_user` WHERE delete_time = 0"
// 查询 admin_user 表的 id、real_name、mobile
sqlStr := "SELECT id, COALESCE(real_name, ''), COALESCE(mobile, '') FROM `admin_user` WHERE delete_time = 0"
args := []interface{}{}
if q != "" {
sqlStr += " AND (CAST(id AS CHAR) LIKE ? OR real_name LIKE ?)"
sqlStr += " AND (CAST(id AS CHAR) LIKE ? OR real_name LIKE ? OR mobile LIKE ?)"
like := "%" + q + "%"
args = append(args, like, like)
args = append(args, like, like, like)
}
sqlStr += " ORDER BY id ASC LIMIT ?"
args = append(args, limit)
@ -53,7 +53,8 @@ func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
for rows.Next() {
var id sql.NullInt64
var name sql.NullString
if err := rows.Scan(&id, &name); err != nil {
var mobile sql.NullString
if err := rows.Scan(&id, &name, &mobile); err != nil {
continue
}
if !id.Valid {
@ -63,8 +64,14 @@ func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
if n == "" {
n = strconv.FormatInt(id.Int64, 10)
}
m := strings.TrimSpace(mobile.String)
display := fmt.Sprintf("%s%d", n, id.Int64)
out = append(out, map[string]interface{}{"id": id.Int64, "name": display})
item := map[string]interface{}{
"id": id.Int64,
"name": display,
"mobile": m,
}
out = append(out, item)
}
ok(w, r, out)
}

View File

@ -272,7 +272,7 @@
<el-row :gutter="8" v-if="isOrder && exportForm.datasource==='marketing'">
<el-col :span="12">
<el-form-item label="订单数据创建者" prop="creator">
<el-select v-model.number="exportForm.creatorId" clearable filterable :disabled="hasOnlyUserId" :teleported="false" placeholder="请选择创建者" style="width:100%">
<el-select v-model.number="exportForm.creatorId" clearable filterable :disabled="hasMobile" :teleported="false" placeholder="请选择创建者" style="width:100%">
<el-option v-for="opt in creatorOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>

View File

@ -24,6 +24,8 @@ const app = createApp({
// ==================== 计算属性 ====================
const hasUserId = Vue.computed(() => !!Api.getUserId());
const hasOnlyUserId = Vue.computed(() => Api.hasOnlyUserId());
// URL 中是否带有 mobile用于营销系统订单数据创建者自动选择 + 禁用
const hasMobile = Vue.computed(() => !!Api.getMobile && !!Api.getMobile());
const currentUserId = Vue.computed(() => {
const userId = Api.getUserId();
return userId ? Number(userId) : null;
@ -664,31 +666,31 @@ const app = createApp({
state.exportForm.datasource = state.exportTpl.datasource || row.datasource || 'marketing';
state.exportForm.file_format = state.exportTpl.file_format || row.file_format || 'xlsx';
// 当 URL 中有 userId 时,自动选中并禁用创建者字段
const userId = Api.getUserId();
const shouldAutoSelectCreator = userId && hasOnlyUserId.value;
console.log('[openExport] userId:', userId, 'hasOnlyUserId:', hasOnlyUserId.value, 'shouldAutoSelectCreator:', shouldAutoSelectCreator);
if (state.exportForm.datasource === 'marketing') {
await loadCreators();
if (shouldAutoSelectCreator) {
const userIdNum = Number(userId);
console.log('[openExport] 设置 marketing creatorId:', userIdNum);
// 直接设置 userId即使创建者列表中暂时没有该选项
state.exportForm.creatorId = userIdNum;
// 等待 Vue 更新
await Vue.nextTick();
const creatorExists = creatorOptions.value.some(opt => opt.value === userIdNum);
console.log('[openExport] creatorOptions:', creatorOptions.value.length, 'creatorExists:', creatorExists);
if (!creatorExists) {
console.log(`警告: 创建者列表中未找到 userId=${userIdNum},但已自动设置`);
// 当 URL 中有 mobile 时,按手机号自动选中并禁用创建者
const mobile = Api.getMobile ? Api.getMobile() : '';
const shouldAutoSelectByMobile = !!mobile;
console.log('[openExport] marketing mobile:', mobile, 'shouldAutoSelectByMobile:', shouldAutoSelectByMobile);
if (shouldAutoSelectByMobile) {
const normalized = String(mobile).trim();
// 在 creatorOptions 中根据 mobile 精确匹配
const match = creatorOptions.value.find(opt => String(opt.mobile || '').trim() === normalized);
if (match) {
console.log('[openExport] 根据手机号匹配到创建者:', match);
state.exportForm.creatorId = match.value;
} else {
console.warn('[openExport] 未根据手机号匹配到创建者, mobile =', normalized);
}
}
}
if (state.exportForm.datasource === 'ymt') {
await loadYmtCreators();
// 仍按 userId 自动选择易码通用户(保持原逻辑)
const userId = Api.getUserId();
const shouldAutoSelectCreator = userId && hasOnlyUserId.value;
console.log('[openExport] ymt userId:', userId, 'hasOnlyUserId:', hasOnlyUserId.value, 'shouldAutoSelectCreator:', shouldAutoSelectCreator);
if (shouldAutoSelectCreator) {
const userIdNum = Number(userId);
console.log('[openExport] 设置 ymt ymtCreatorId:', userIdNum);
@ -716,25 +718,8 @@ const app = createApp({
state.exportVisible = true;
// 对话框打开后,再次确保值已设置(处理异步加载和渲染的情况)
// 对话框打开后,无需再根据 userId 处理营销系统创建者,手机号逻辑已在上方完成
await Vue.nextTick();
// 使用 setTimeout 确保在对话框完全渲染后再设置值
setTimeout(() => {
if (shouldAutoSelectCreator) {
const userIdNum = Number(userId);
if (state.exportForm.datasource === 'marketing') {
if (state.exportForm.creatorId !== userIdNum) {
console.log('[openExport] 对话框打开后重新设置 marketing creatorId:', userIdNum);
state.exportForm.creatorId = userIdNum;
}
} else if (state.exportForm.datasource === 'ymt') {
if (state.exportForm.ymtCreatorId !== userIdNum) {
console.log('[openExport] 对话框打开后重新设置 ymt ymtCreatorId:', userIdNum);
state.exportForm.ymtCreatorId = userIdNum;
}
}
}
}, 100);
};
/**
@ -1128,6 +1113,7 @@ const app = createApp({
exportTitle,
hasUserId,
hasOnlyUserId,
hasMobile,
currentUserId,
hasCreators,
hasReseller,

View File

@ -39,6 +39,16 @@ const hasOnlyUserId = () => {
return !!(value && String(value).trim());
};
/**
* URL 参数中获取手机号用于营销系统订单数据创建者自动选择
* @returns {string} 手机号不存在返回空字符串
*/
const getMobile = () => {
const params = new URLSearchParams(window.location.search || '');
const value = params.get('mobile');
return value && String(value).trim() ? String(value).trim() : '';
};
/**
* URL 参数中获取商户 ID
* @returns {string} 商户 ID不存在返回空字符串
@ -335,12 +345,16 @@ const fetchFieldsMetadata = async (datasource, orderType) => {
/**
* 加载创建者列表营销系统
* @returns {Promise<Array<{label: string, value: number}>>} 选项数组
* @returns {Promise<Array<{label: string, value: number, mobile?: string}>>} 选项数组
*/
const fetchCreators = async () => {
const data = await get('/api/creators');
const arr = parseArrayResponse(data);
return arr.map(it => ({ label: it.name || String(it.id), value: Number(it.id) }));
return arr.map(it => ({
label: it.name || String(it.id),
value: Number(it.id),
mobile: it.mobile ? String(it.mobile).trim() : ''
}));
};
/**
@ -409,6 +423,7 @@ window.ApiService = {
// 基础方法
API_BASE,
getUserId,
getMobile,
hasOnlyUserId,
getMerchantId,
buildUserQueryString,