liujie
昨天 384bce80449b17651937429038c4370dbce60e7b
hugray-server/ruoyi-modules/ruoyi-user/src/main/resources/mapper/user/AccountUserMapper.xml
@@ -5,28 +5,60 @@
<mapper namespace="com.ruoyi.user.mapper.AccountUserMapper">
    <resultMap type="AccountUser" id="AccountUserResult">
        <id     property="userId"     column="user_id"     />
        <result property="userName"   column="username"    />
        <result property="phone"      column="phone"       />
        <result property="password"   column="password"    />
        <result property="nickname"   column="nickname"    />
        <result property="avatar"     column="avatar"      />
        <result property="gender"     column="gender"      />
        <result property="birthday"   column="birthday"    />
        <result property="status"     column="status"      />
        <result property="delFlag"    column="del_flag"    />
        <id     property="userId"          column="user_id"           />
        <result property="userName"        column="username"          />
        <result property="phone"           column="phone"             />
        <result property="password"        column="password"          />
        <result property="nickname"        column="nickname"          />
        <result property="avatar"          column="avatar"            />
        <result property="gender"          column="gender"            />
        <result property="birthday"        column="birthday"          />
        <result property="status"          column="status"            />
        <result property="systemLevel"     column="system_level"      />
        <result property="subjectType"     column="subject_type"      />
        <result property="authStatus"      column="auth_status"       />
        <result property="city"            column="city"              />
        <result property="referrerId"      column="referrer_id"       />
        <result property="referrerBindTime" column="referrer_bind_time" />
        <result property="supplierId"      column="supplier_id"       />
        <result property="supplierBindTime" column="supplier_bind_time" />
        <result property="buyOrderCount"     column="buy_order_count"      />
        <result property="buyAmountTotal"    column="buy_amount_total"     />
        <result property="sellOrderCount"    column="sell_order_count"     />
        <result property="sellAmountTotal"   column="sell_amount_total"    />
        <result property="purchaseOrderCount" column="purchase_order_count" />
        <result property="purchaseAmountTotal" column="purchase_amount_total" />
        <result property="sellProfitTotal"   column="sell_profit_total"    />
        <result property="virtualStockQty"   column="virtual_stock_qty"    />
        <result property="virtualStockValue" column="virtual_stock_value"  />
        <result property="delFlag"         column="del_flag"          />
        <result property="myReferralCode"   column="my_referral_code"   />
        <result property="referrerId"       column="referrer_id"        />
        <result property="systemLevel"      column="system_level"       />
        <result property="createBy"   column="create_by"   />
        <result property="createTime" column="create_time" />
        <result property="updateBy"   column="update_by"   />
        <result property="updateTime" column="update_time" />
        <result property="remark"     column="remark"      />
        <result property="providerFlag"    column="provider_flag"     />
        <result property="createBy"        column="create_by"         />
        <result property="createTime"      column="create_time"       />
        <result property="updateBy"        column="update_by"         />
        <result property="updateTime"      column="update_time"       />
        <result property="remark"          column="remark"            />
    </resultMap>
    <!-- 详情专用:在 AccountUserResult 基础上追加推荐人/供货人的派生列 -->
    <resultMap type="AccountUserVo" id="AccountUserVoResult" extends="AccountUserResult">
        <result property="referrerPhone"    column="referrer_phone"    />
        <result property="referrerLevel"    column="referrer_level"    />
        <result property="referrerNickname" column="referrer_nickname" />
        <result property="supplierPhone"    column="supplier_phone"    />
        <result property="supplierLevel"    column="supplier_level"    />
        <result property="supplierNickname" column="supplier_nickname" />
    </resultMap>
    <sql id="selectAccountUserVo">
        select user_id, username, phone, password, nickname, avatar, gender, birthday, status, del_flag, my_referral_code, referrer_id, system_level, create_by, create_time, update_by, update_time, remark
        select user_id, username, phone, password, nickname, avatar, gender, birthday, status,
               system_level, subject_type, auth_status, city,
               referrer_id, referrer_bind_time, supplier_id, supplier_bind_time,
               buy_order_count, buy_amount_total, sell_order_count, sell_amount_total,
               purchase_order_count, purchase_amount_total, sell_profit_total,
               virtual_stock_qty, virtual_stock_value,my_referral_code,
               del_flag, provider_flag, create_by, create_time, update_by, update_time, remark
        from account_user
    </sql>
@@ -34,16 +66,28 @@
        <include refid="selectAccountUserVo"/>
        <where>
            del_flag = '0'
            <if test="userId != null"> and user_id = #{userId}</if>
            <!-- 手机号按完整号码精确匹配:列表筛选是「用户手机」,C 端按全号检索是常态;
                 且 like '%x%' 的前缀通配会让 idx_account_user_phone 完全失效。 -->
            <if test="phone != null and phone != ''"> and phone = #{phone}</if>
            <if test="userName != null and userName != ''"> and username like concat('%', #{userName}, '%')</if>
            <if test="phone != null and phone != ''"> and phone like concat('%', #{phone}, '%')</if>
            <if test="nickname != null and nickname != ''"> and nickname like concat('%', #{nickname}, '%')</if>
            <if test="gender != null and gender != ''"> and gender = #{gender}</if>
            <if test="status != null and status != ''"> and status = #{status}</if>
            <if test="systemLevel != null and systemLevel != ''"> and system_level = #{systemLevel}</if>
            <if test="authStatus != null and authStatus != ''"> and auth_status = #{authStatus}</if>
            <if test="subjectType != null and subjectType != ''"> and subject_type = #{subjectType}</if>
            <!-- 城市按名称精确匹配,选项来自 account_city 的启用城市:
                 城市表按「省 + 市」两列存,但会员表只有 city(市级、无省份),故筛选口径就是市名。
                 原先那套「只选省时把该省全部市名拼成 IN」的逻辑随城市主数据扁平化一起去掉了。 -->
            <if test="city != null and city != ''"> and city = #{city}</if>
            <!-- 时间范围必须是 sargable 写法:原来的 date_format(create_time,'%y%m%d') 把列包在函数里,
                 create_time 上的索引用不上,数据量上来后是全表扫。 -->
            <if test="params.beginTime != null and params.beginTime != ''">
                and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
                and create_time &gt;= #{params.beginTime}
            </if>
            <if test="params.endTime != null and params.endTime != ''">
                and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
                and create_time &lt; date_add(#{params.endTime}, interval 1 day)
            </if>
        </where>
        order by user_id desc
@@ -64,9 +108,25 @@
        where del_flag = '0' and phone = #{phone}
    </select>
    <select id="selectAccountUserByReferralCode" parameterType="String" resultMap="AccountUserResult">
        <include refid="selectAccountUserVo"/>
        where del_flag = '0' and my_referral_code = #{referralCode}
    <!--
        详情查询:会员本体 + 推荐人/供货人的手机号、等级、昵称。
        两次自连接都走 user_id 主键,成本极低。
        条件里的 del_flag = '0' 不可省:推荐人可能已被逻辑删除(造数脚本的 user_id=125
        引用已删除的 124 就是这种边界行),漏掉它会关联出已删除用户的信息。
        仅供详情使用——列表带分页,挂 join 会干扰 PageHelper 的 count SQL。
    -->
    <select id="selectAccountUserVoById" parameterType="Long" resultMap="AccountUserVoResult">
        select u.*,
               r.phone        as referrer_phone,
               r.system_level as referrer_level,
               r.nickname     as referrer_nickname,
               s.phone        as supplier_phone,
               s.system_level as supplier_level,
               s.nickname     as supplier_nickname
        from account_user u
        left join account_user r on r.user_id = u.referrer_id and r.del_flag = '0'
        left join account_user s on s.user_id = u.supplier_id and s.del_flag = '0'
        where u.del_flag = '0' and u.user_id = #{userId}
    </select>
    <insert id="insertAccountUser" parameterType="AccountUser" useGeneratedKeys="true" keyProperty="userId">
@@ -79,9 +139,15 @@
            <if test="gender != null and gender != ''">gender,</if>
            <if test="birthday != null">birthday,</if>
            <if test="status != null and status != ''">status,</if>
            <if test="myReferralCode != null and myReferralCode != ''">my_referral_code,</if>
        <if test="myReferralCode != null and myReferralCode != ''">my_referral_code,</if>
        <if test="systemLevel != null and systemLevel != ''">system_level,</if>
            <if test="subjectType != null and subjectType != ''">subject_type,</if>
            <if test="authStatus != null and authStatus != ''">auth_status,</if>
            <if test="city != null and city != ''">city,</if>
            <if test="referrerId != null">referrer_id,</if>
            <if test="systemLevel != null and systemLevel != ''">system_level,</if>
            <if test="referrerBindTime != null">referrer_bind_time,</if>
            <if test="supplierId != null">supplier_id,</if>
            <if test="supplierBindTime != null">supplier_bind_time,</if>
            <if test="remark != null">remark,</if>
            <if test="createBy != null and createBy != ''">create_by,</if>
            create_time
@@ -94,9 +160,16 @@
            <if test="gender != null and gender != ''">#{gender},</if>
            <if test="birthday != null">#{birthday},</if>
            <if test="status != null and status != ''">#{status},</if>
            <if test="myReferralCode != null and myReferralCode != ''">#{myReferralCode},</if>
        <if test="myReferralCode != null and myReferralCode != ''">#{myReferralCode},</if>
        <if test="systemLevel != null and systemLevel != ''">#{systemLevel},</if>
            <if test="subjectType != null and subjectType != ''">#{subjectType},</if>
            <if test="authStatus != null and authStatus != ''">#{authStatus},</if>
            <if test="city != null and city != ''">#{city},</if>
            <if test="referrerId != null">#{referrerId},</if>
            <if test="systemLevel != null and systemLevel != ''">#{systemLevel},</if>
            <if test="referrerBindTime != null">#{referrerBindTime},</if>
            <if test="supplierId != null">#{supplierId},</if>
            <if test="supplierBindTime != null">#{supplierBindTime},</if>
            <if test="remark != null">#{remark},</if>
            <if test="createBy != null and createBy != ''">#{createBy},</if>
            sysdate()
@@ -115,10 +188,73 @@
            <if test="birthday != null">birthday = #{birthday},</if>
            <if test="status != null and status != ''">status = #{status},</if>
            <if test="myReferralCode != null and myReferralCode != ''">my_referral_code = #{myReferralCode},</if>
            <if test="referrerId != null">referrer_id = #{referrerId},</if>
            <if test="systemLevel != null and systemLevel != ''">system_level = #{systemLevel},</if>
            <if test="subjectType != null and subjectType != ''">subject_type = #{subjectType},</if>
            <if test="authStatus != null and authStatus != ''">auth_status = #{authStatus},</if>
            <if test="city != null">city = #{city},</if>
            <if test="referrerId != null">referrer_id = #{referrerId},</if>
            <if test="referrerBindTime != null">referrer_bind_time = #{referrerBindTime},</if>
            <if test="supplierId != null">supplier_id = #{supplierId},</if>
            <if test="supplierBindTime != null">supplier_bind_time = #{supplierBindTime},</if>
            <if test="remark != null">remark = #{remark},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where user_id = #{userId} and del_flag = '0'
    </update>
    <!--
        关系修改专用。不能复用 updateAccountUser:一是那里按 <if> 拼列,传不全也没问题,
        但业务上不该允许借这个口子改别的字段;二是 Controller 侧的统一校验链路
        (@NotBlank userName、用户名/手机号查重)会拦下只传关系的请求。
        referrerId / supplierId 传 null 即为解除绑定(<set> 里直接赋值,不走 <if>)。
    -->
    <update id="updateUserRelation" parameterType="AccountUser">
        update account_user
        <set>
            referrer_id        = #{referrerId},
            referrer_bind_time = #{referrerBindTime},
            supplier_id        = #{supplierId},
            supplier_bind_time = #{supplierBindTime},
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where user_id = #{userId} and del_flag = '0'
    </update>
    <!-- 状态变更专用:同上,避免与整体编辑共用校验链路 -->
    <update id="updateUserStatus" parameterType="AccountUser">
        update account_user
        <set>
            status = #{status},
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where user_id = #{userId} and del_flag = '0'
    </update>
    <!-- 主体认证审核通过/驳回后回写认证状态,只动 auth_status 一列 -->
    <update id="updateUserAuthStatus" parameterType="AccountUser">
        update account_user
        <set>
            auth_status = #{authStatus},
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where user_id = #{userId} and del_flag = '0'
    </update>
    <!--
        服务商标识专用:与 updateUserAuthStatus 同一个套路——别的模块要给会员打标识,
        就单开一条只写该列的语句,绝不挂到共享的 insertAccountUser / updateAccountUser 上
        (那两个按 <if> 拼列,挂上去等于 /account/user 的请求体里带个 providerFlag 就能自己打标)。
        当前唯一调用方是服务商模块。
    -->
    <update id="updateUserProviderFlag" parameterType="AccountUser">
        update account_user
        <set>
            provider_flag = #{providerFlag},
            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
            update_time = sysdate()
        </set>
        where user_id = #{userId} and del_flag = '0'
@@ -136,4 +272,64 @@
        </foreach>
    </update>
    <resultMap type="MemberOptionVo" id="MemberOptionVoResult">
        <id     property="userId"      column="user_id"      />
        <result property="memberName"  column="member_name"  />
        <result property="phone"       column="phone"        />
        <result property="systemLevel" column="system_level" />
    </resultMap>
    <!--
        城市公司档案表单的「关联用户信息」下拉:只搜 L4(档案的准入条件)。
        显示名取认证表的真实姓名,无认证资料时回落昵称;两者都为空则前端按会员编号展示。
        limit 20 是必要的:下拉是随打随搜的,不设上限等于把「输一个 1」变成全表 like。
        该查询不分页,故 join 不会干扰 PageHelper 的 count SQL。
    -->
    <select id="selectL4MemberOptions" resultMap="MemberOptionVoResult">
        select u.user_id, u.phone, u.system_level,
               coalesce(nullif(cert.real_name, ''), u.nickname) as member_name
        from account_user u
        left join account_certification cert on cert.user_id = u.user_id and cert.del_flag = '0'
        where u.del_flag = '0' and u.system_level = 'L4'
        <if test="keyword != null and keyword != ''">
            and (u.phone    like concat('%', #{keyword}, '%')
                 or u.nickname   like concat('%', #{keyword}, '%')
                 or cert.real_name like concat('%', #{keyword}, '%')
                 <if test="keywordId != null"> or u.user_id = #{keywordId}</if>)
        </if>
        order by u.user_id desc
        limit 20
    </select>
    <!--
        修改供货人的「新供货人」下拉:只搜等级严格高于该会员的会员。
        levels 由服务层按 AccountUser.levelsAbove 算好,且必须非空——空集合会拼成
        in () 的语法错误(该会员已是最高等级时服务层提前返回,走不到这条语句)。
        其余口径刻意与 selectL4MemberOptions 保持一致:显示名取认证表真实姓名、无认证
        回落昵称;手机号/昵称/姓名模糊 + 纯数字 keywordId 等值命中编号;limit 20 是必要的
        (随打随搜不设上限,等于把「输一个 1」变成全表 like)。
        user_id != #{userId} 既保证不自环,也顺带把会员自己从候选里摘掉。
    -->
    <select id="selectSupplierCandidates" resultMap="MemberOptionVoResult">
        select u.user_id, u.phone, u.system_level,
               coalesce(nullif(cert.real_name, ''), u.nickname) as member_name
        from account_user u
        left join account_certification cert on cert.user_id = u.user_id and cert.del_flag = '0'
        where u.del_flag = '0'
          and u.user_id != #{userId}
          and u.system_level in
        <foreach item="level" collection="levels" open="(" separator="," close=")">
            #{level}
        </foreach>
        <if test="keyword != null and keyword != ''">
            and (u.phone    like concat('%', #{keyword}, '%')
                 or u.nickname   like concat('%', #{keyword}, '%')
                 or cert.real_name like concat('%', #{keyword}, '%')
                 <if test="keywordId != null"> or u.user_id = #{keywordId}</if>)
        </if>
        order by u.user_id desc
        limit 20
    </select>
</mapper>