diff --git a/server/internal/api/creators.go b/server/internal/api/creators.go index 0e9af8b..5f74eba 100644 --- a/server/internal/api/creators.go +++ b/server/internal/api/creators.go @@ -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) } diff --git a/web/index.html b/web/index.html index 726566e..27f2c67 100644 --- a/web/index.html +++ b/web/index.html @@ -272,7 +272,7 @@ - + diff --git a/web/main.js b/web/main.js index e9d45da..15a1b33 100644 --- a/web/main.js +++ b/web/main.js @@ -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, diff --git a/web/modules/api.js b/web/modules/api.js index ea2ff21..b638673 100644 --- a/web/modules/api.js +++ b/web/modules/api.js @@ -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>} 选项数组 + * @returns {Promise>} 选项数组 */ 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,