1、用户注册V1
2、修复营销编号校验bug 3、其他优化
This commit is contained in:
parent
8794357859
commit
5ae10027cd
@ -1,5 +1,11 @@
|
|||||||
export const REG_USER_NAME = /^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/;
|
export const REG_USER_NAME = /^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/;
|
||||||
|
|
||||||
|
export const REG_NICK_NAME = /^[\u4e00-\u9fa5]{2,8}$/;
|
||||||
|
|
||||||
|
export const ID_CARD_NO = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
|
||||||
|
|
||||||
|
export const MKT_NO = /[A-Za-z0-9]{6}/;
|
||||||
|
|
||||||
/** Phone reg */
|
/** Phone reg */
|
||||||
export const REG_PHONE =
|
export const REG_PHONE =
|
||||||
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/;
|
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { ref, toValue } from 'vue';
|
import { ref, toValue } from 'vue';
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
import type { FormInst } from 'naive-ui';
|
import type { FormInst } from 'naive-ui';
|
||||||
import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg';
|
import {ID_CARD_NO, MKT_NO, REG_CODE_SIX, REG_EMAIL, REG_NICK_NAME, REG_PHONE, REG_PWD, REG_USER_NAME} from '@/constants/reg';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
export function useFormRules() {
|
export function useFormRules() {
|
||||||
@ -11,6 +11,21 @@ export function useFormRules() {
|
|||||||
message: $t('form.userName.invalid'),
|
message: $t('form.userName.invalid'),
|
||||||
trigger: ['change', 'blur']
|
trigger: ['change', 'blur']
|
||||||
},
|
},
|
||||||
|
nickName: {
|
||||||
|
pattern: REG_NICK_NAME,
|
||||||
|
message: $t('form.nickName.invalid'),
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
},
|
||||||
|
idCard: {
|
||||||
|
pattern: ID_CARD_NO,
|
||||||
|
message: $t('form.idCard.invalid'),
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
},
|
||||||
|
mktNo: {
|
||||||
|
pattern: MKT_NO,
|
||||||
|
message: $t('form.mktNo.invalid'),
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
},
|
||||||
phone: {
|
phone: {
|
||||||
pattern: REG_PHONE,
|
pattern: REG_PHONE,
|
||||||
message: $t('form.phone.invalid'),
|
message: $t('form.phone.invalid'),
|
||||||
@ -35,6 +50,9 @@ export function useFormRules() {
|
|||||||
|
|
||||||
const formRules = {
|
const formRules = {
|
||||||
userName: [createRequiredRule($t('form.userName.required')), patternRules.userName],
|
userName: [createRequiredRule($t('form.userName.required')), patternRules.userName],
|
||||||
|
nickName: [createRequiredRule($t('form.nickName.required')), patternRules.nickName],
|
||||||
|
idCard: [createRequiredRule($t('form.idCard.required')), patternRules.idCard],
|
||||||
|
mktNo: [createRequiredRule($t('form.mktNo.required')), patternRules.mktNo],
|
||||||
phone: [createRequiredRule($t('form.phone.required')), patternRules.phone],
|
phone: [createRequiredRule($t('form.phone.required')), patternRules.phone],
|
||||||
pwd: [createRequiredRule($t('form.pwd.required')), patternRules.pwd],
|
pwd: [createRequiredRule($t('form.pwd.required')), patternRules.pwd],
|
||||||
code: [createRequiredRule($t('form.code.required')), patternRules.code],
|
code: [createRequiredRule($t('form.code.required')), patternRules.code],
|
||||||
|
|||||||
@ -1174,9 +1174,21 @@ const local: App.I18n.Schema = {
|
|||||||
form: {
|
form: {
|
||||||
required: 'Cannot be empty',
|
required: 'Cannot be empty',
|
||||||
userName: {
|
userName: {
|
||||||
|
required: 'Please enter login name',
|
||||||
|
invalid: 'Login name format is incorrect'
|
||||||
|
},
|
||||||
|
nickName: {
|
||||||
required: 'Please enter user name',
|
required: 'Please enter user name',
|
||||||
invalid: 'User name format is incorrect'
|
invalid: 'User name format is incorrect'
|
||||||
},
|
},
|
||||||
|
idCard: {
|
||||||
|
required: 'Please enter id card no',
|
||||||
|
invalid: 'Id card no format is incorrect'
|
||||||
|
},
|
||||||
|
mktNo: {
|
||||||
|
required: 'Please enter mkt no',
|
||||||
|
invalid: 'Mkt no format is incorrect'
|
||||||
|
},
|
||||||
phone: {
|
phone: {
|
||||||
required: 'Please enter phone number',
|
required: 'Please enter phone number',
|
||||||
invalid: 'Phone number format is incorrect'
|
invalid: 'Phone number format is incorrect'
|
||||||
|
|||||||
@ -340,7 +340,7 @@ const local: App.I18n.Schema = {
|
|||||||
common: {
|
common: {
|
||||||
loginOrRegister: '登录 / 注册',
|
loginOrRegister: '登录 / 注册',
|
||||||
register: '注册',
|
register: '注册',
|
||||||
userNamePlaceholder: '请输入用户名',
|
userNamePlaceholder: '请输入登录用户名',
|
||||||
phonePlaceholder: '请输入手机号',
|
phonePlaceholder: '请输入手机号',
|
||||||
codePlaceholder: '请输入验证码',
|
codePlaceholder: '请输入验证码',
|
||||||
passwordPlaceholder: '请输入密码',
|
passwordPlaceholder: '请输入密码',
|
||||||
@ -1182,8 +1182,20 @@ const local: App.I18n.Schema = {
|
|||||||
form: {
|
form: {
|
||||||
required: '不能为空',
|
required: '不能为空',
|
||||||
userName: {
|
userName: {
|
||||||
required: '请输入用户名',
|
required: '请输入登录名',
|
||||||
invalid: '用户名格式不正确'
|
invalid: '登录名格式不正确'
|
||||||
|
},
|
||||||
|
nickName: {
|
||||||
|
required: '请输入姓名',
|
||||||
|
invalid: '姓名必须为2-8位中文'
|
||||||
|
},
|
||||||
|
idCard: {
|
||||||
|
required: '请输入身份证号码',
|
||||||
|
invalid: '身份证号码格式不正确'
|
||||||
|
},
|
||||||
|
mktNo: {
|
||||||
|
required: '请输入营销编号',
|
||||||
|
invalid: '营销编号格式不正确'
|
||||||
},
|
},
|
||||||
phone: {
|
phone: {
|
||||||
required: '请输入手机号',
|
required: '请输入手机号',
|
||||||
|
|||||||
@ -83,6 +83,17 @@ export function fetchGetDeptTree() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取部门树列表 */
|
||||||
|
export function fetchGetRegDeptTree(tenantId: string) {
|
||||||
|
return request<Api.Common.CommonTreeRecord>({
|
||||||
|
url: '/system/user/regDeptTree',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
tenantId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 重置用户密码 */
|
/** 重置用户密码 */
|
||||||
export function fetchResetUserPassword(userId: CommonType.IdType, password: string) {
|
export function fetchResetUserPassword(userId: CommonType.IdType, password: string) {
|
||||||
return request<boolean>({
|
return request<boolean>({
|
||||||
|
|||||||
13
cds-fontend-2025.V1/src/typings/api/api.d.ts
vendored
13
cds-fontend-2025.V1/src/typings/api/api.d.ts
vendored
@ -126,7 +126,7 @@ declare namespace Api {
|
|||||||
|
|
||||||
/** register form */
|
/** register form */
|
||||||
interface RegisterForm extends LoginForm {
|
interface RegisterForm extends LoginForm {
|
||||||
/** 用户名 */
|
/** 登录名 */
|
||||||
username?: string;
|
username?: string;
|
||||||
/** 密码 */
|
/** 密码 */
|
||||||
password?: string;
|
password?: string;
|
||||||
@ -134,6 +134,17 @@ declare namespace Api {
|
|||||||
confirmPassword?: string;
|
confirmPassword?: string;
|
||||||
/** 用户类型 */
|
/** 用户类型 */
|
||||||
userType?: string;
|
userType?: string;
|
||||||
|
|
||||||
|
/** 姓名 */
|
||||||
|
nickName: '',
|
||||||
|
/** 身份证号 */
|
||||||
|
idCard: '',
|
||||||
|
/*用户种类(0-营销 1-其他)*/
|
||||||
|
userCategory: '1',//注意跟字典保持一致
|
||||||
|
/** 营销编号 */
|
||||||
|
mktNo: '',
|
||||||
|
/** 部门编号 */
|
||||||
|
deptId: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** login token data */
|
/** login token data */
|
||||||
|
|||||||
@ -179,12 +179,12 @@ async function handleSocialLogin(type: Api.System.SocialSource) {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
</NForm>
|
</NForm>
|
||||||
|
|
||||||
<NDivider>
|
<!-- <NDivider>
|
||||||
<!-- <div class="color-#858585">{{ $t('page.login.pwdLogin.otherAccountLogin') }}</div>-->
|
<!– <div class="color-#858585">{{ $t('page.login.pwdLogin.otherAccountLogin') }}</div>–>
|
||||||
|
|
||||||
评估是否增加注册功能
|
评估是否增加注册功能
|
||||||
|
|
||||||
</NDivider>
|
</NDivider>-->
|
||||||
|
|
||||||
<!-- <div class="w-full flex-y-center gap-16px">
|
<!-- <div class="w-full flex-y-center gap-16px">
|
||||||
<NButton class="flex-1" @click="handleSocialLogin('gitee')">
|
<NButton class="flex-1" @click="handleSocialLogin('gitee')">
|
||||||
@ -201,12 +201,12 @@ async function handleSocialLogin(type: Api.System.SocialSource) {
|
|||||||
</NButton>
|
</NButton>
|
||||||
</div>-->
|
</div>-->
|
||||||
|
|
||||||
<!-- <div class="mt-32px w-full text-center text-18px text-#858585">
|
<div class="mt-32px w-full text-center text-18px text-#858585">
|
||||||
您还没有账户?
|
您还没有账户?
|
||||||
<NA type="primary" class="text-18px" @click="toggleLoginModule('register')">
|
<NA type="primary" class="text-18px" @click="toggleLoginModule('register')">
|
||||||
{{ $t('page.login.common.register') }}
|
{{ $t('page.login.common.register') }}
|
||||||
</NA>
|
</NA>
|
||||||
</div>-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import { fetchCaptchaCode, fetchRegister, fetchTenantList } from '@/service/api'
|
|||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
import { fetchGetRegDeptTree} from "@/service/api/system";
|
||||||
|
import {useDict} from "@/hooks/business/dict";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'Register'
|
name: 'Register'
|
||||||
@ -15,19 +17,29 @@ const { toggleLoginModule } = useRouterPush();
|
|||||||
const { formRef, validate } = useNaiveForm();
|
const { formRef, validate } = useNaiveForm();
|
||||||
const { loading: codeLoading, startLoading: startCodeLoading, endLoading: endCodeLoading } = useLoading();
|
const { loading: codeLoading, startLoading: startCodeLoading, endLoading: endCodeLoading } = useLoading();
|
||||||
const { loading: registerLoading, startLoading: startRegisterLoading, endLoading: endRegisterLoading } = useLoading();
|
const { loading: registerLoading, startLoading: startRegisterLoading, endLoading: endRegisterLoading } = useLoading();
|
||||||
|
const { loading: deptLoading, startLoading: startDeptLoading, endLoading: endDeptLoading } = useLoading();
|
||||||
|
const { loading: treeLoading, startLoading: startTreeLoading, endLoading: endTreeLoading } = useLoading();
|
||||||
|
|
||||||
const codeUrl = ref<string>();
|
const codeUrl = ref<string>();
|
||||||
const captchaEnabled = ref<boolean>(false);
|
const captchaEnabled = ref<boolean>(false);
|
||||||
const tenantEnabled = ref<boolean>(false);
|
const tenantEnabled = ref<boolean>(false);
|
||||||
const tenantOption = ref<SelectOption[]>([]);
|
const tenantOption = ref<SelectOption[]>([]);
|
||||||
|
const deptData = ref<Api.Common.CommonTreeRecord>([]);
|
||||||
|
const {options: mpsUserCategory} = useDict('mps_user_category');
|
||||||
|
|
||||||
const model: Api.Auth.RegisterForm = reactive({
|
const model: Api.Auth.RegisterForm = reactive({
|
||||||
tenantId: '000000',
|
/*tenantId: '000000',*/
|
||||||
|
tenantId: '069291',//注意要和部署法人保持一致
|
||||||
username: '',
|
username: '',
|
||||||
|
nickName: '',
|
||||||
|
idCard: '',
|
||||||
|
userCategory: '1',//注意跟字典保持一致
|
||||||
|
mktNo: '',
|
||||||
code: '',
|
code: '',
|
||||||
password: '',
|
password: '',
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
userType: 'sys_user'
|
userType: 'sys_user',
|
||||||
|
deptId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
type RuleKey = Extract<keyof Api.Auth.RegisterForm, 'username' | 'password' | 'confirmPassword' | 'code' | 'tenantId'>;
|
type RuleKey = Extract<keyof Api.Auth.RegisterForm, 'username' | 'password' | 'confirmPassword' | 'code' | 'tenantId'>;
|
||||||
@ -38,12 +50,26 @@ const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
|||||||
return {
|
return {
|
||||||
tenantId: tenantEnabled.value ? formRules.tenantId : [],
|
tenantId: tenantEnabled.value ? formRules.tenantId : [],
|
||||||
username: [...formRules.userName, { required: true }],
|
username: [...formRules.userName, { required: true }],
|
||||||
|
nickName: [...formRules.nickName, { required: true }],
|
||||||
|
idCard: [...formRules.idCard, { required: true }],
|
||||||
|
mktNo: [...formRules.mktNo, { required: true }],
|
||||||
password: [...formRules.pwd, { required: true }],
|
password: [...formRules.pwd, { required: true }],
|
||||||
confirmPassword: createConfirmPwdRule(model.password!),
|
confirmPassword: createConfirmPwdRule(model.password!),
|
||||||
code: captchaEnabled.value ? [createRequiredRule($t('form.code.required'))] : []
|
code: captchaEnabled.value ? [createRequiredRule($t('form.code.required'))] : []
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function getTreeData() {
|
||||||
|
startTreeLoading();
|
||||||
|
const { data: tree, error } = await fetchGetRegDeptTree(model.tenantId);
|
||||||
|
if (!error) {
|
||||||
|
deptData.value = tree;
|
||||||
|
}
|
||||||
|
endTreeLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeData();
|
||||||
|
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
try {
|
try {
|
||||||
await validate();
|
await validate();
|
||||||
@ -56,7 +82,18 @@ async function handleSubmit() {
|
|||||||
uuid: model.uuid,
|
uuid: model.uuid,
|
||||||
grantType: 'password',
|
grantType: 'password',
|
||||||
userType: model.userType,
|
userType: model.userType,
|
||||||
clientId: import.meta.env.VITE_APP_CLIENT_ID
|
clientId: import.meta.env.VITE_APP_CLIENT_ID,
|
||||||
|
|
||||||
|
/** 姓名 */
|
||||||
|
nickName: model.nickName,
|
||||||
|
/** 身份证号 */
|
||||||
|
idCard: model.idCard,
|
||||||
|
/*用户种类(0-营销 1-其他)*/
|
||||||
|
userCategory: model.userCategory,//注意跟字典保持一致
|
||||||
|
/** 营销编号 */
|
||||||
|
mktNo: model.mktNo,
|
||||||
|
/** 部门编号 */
|
||||||
|
deptId: model.deptId,
|
||||||
});
|
});
|
||||||
if (error) {
|
if (error) {
|
||||||
handleFetchCaptchaCode();
|
handleFetchCaptchaCode();
|
||||||
@ -111,16 +148,60 @@ handleFetchCaptchaCode();
|
|||||||
:model="model"
|
:model="model"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
size="large"
|
size="large"
|
||||||
:show-label="false"
|
:show-label="true"
|
||||||
|
label-placement="left"
|
||||||
|
:label-width="100"
|
||||||
@keyup.enter="() => !registerLoading && handleSubmit()"
|
@keyup.enter="() => !registerLoading && handleSubmit()"
|
||||||
>
|
>
|
||||||
<NFormItem v-if="tenantEnabled" path="tenantId">
|
|
||||||
|
<!-- 法人、部门 -->
|
||||||
|
<NFormItem label="所属法人" v-if="tenantEnabled" path="tenantId">
|
||||||
<NSelect v-model:value="model.tenantId" :options="tenantOption" :enabled="tenantEnabled" />
|
<NSelect v-model:value="model.tenantId" :options="tenantOption" :enabled="tenantEnabled" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem path="username">
|
<NFormItem required :label="$t('page.system.user.deptName')" path="deptId">
|
||||||
|
<NTreeSelect
|
||||||
|
v-model:value="model.deptId"
|
||||||
|
:loading="deptLoading"
|
||||||
|
clearable
|
||||||
|
:options="deptData as []"
|
||||||
|
label-field="label"
|
||||||
|
key-field="id"
|
||||||
|
:default-expanded-keys="deptData?.length ? [deptData[0].id] : []"
|
||||||
|
:placeholder="$t('page.system.user.form.deptId.required')"
|
||||||
|
:default-value="deptData?.length ? [deptData[0].id] : null"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 营销 -->
|
||||||
|
<NFormItem required label="用户类别" path="userCategory">
|
||||||
|
<NSelect
|
||||||
|
v-model:value="model.userCategory"
|
||||||
|
placeholder="请选择用户类别"
|
||||||
|
:options="mpsUserCategory"
|
||||||
|
|
||||||
|
filterable
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem v-if="model.userCategory === '0'" label="营销编号" path="mktNo" required>
|
||||||
|
<NInput v-model:value="model.mktNo" :placeholder="$t('page.system.user.form.mktNo.required')" />
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 真实用户信息 -->
|
||||||
|
<NFormItem required label="姓名" path="nickName">
|
||||||
|
<NInput v-model:value="model.nickName" :placeholder="$t('form.nickName.required')" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem required label="身份证号" path="idCard">
|
||||||
|
<NInput v-model:value="model.idCard" :placeholder="$t('form.idCard.required')" />
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 登录用户信息 -->
|
||||||
|
<NFormItem required label="登录名" path="username">
|
||||||
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem path="password">
|
<NFormItem required label="登陆密码" path="password">
|
||||||
<NInput
|
<NInput
|
||||||
v-model:value="model.password"
|
v-model:value="model.password"
|
||||||
type="password"
|
type="password"
|
||||||
@ -128,7 +209,7 @@ handleFetchCaptchaCode();
|
|||||||
:placeholder="$t('page.login.common.passwordPlaceholder')"
|
:placeholder="$t('page.login.common.passwordPlaceholder')"
|
||||||
/>
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem path="confirmPassword">
|
<NFormItem required label="登录密码" path="confirmPassword">
|
||||||
<NInput
|
<NInput
|
||||||
v-model:value="model.confirmPassword"
|
v-model:value="model.confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
@ -136,7 +217,7 @@ handleFetchCaptchaCode();
|
|||||||
:placeholder="$t('page.login.common.confirmPasswordPlaceholder')"
|
:placeholder="$t('page.login.common.confirmPasswordPlaceholder')"
|
||||||
/>
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem v-if="captchaEnabled" path="code">
|
<NFormItem required label="验证码" v-if="captchaEnabled" path="code">
|
||||||
<div class="w-full flex-y-center gap-16px">
|
<div class="w-full flex-y-center gap-16px">
|
||||||
<NInput v-model:value="model.code" :placeholder="$t('page.login.common.codePlaceholder')" />
|
<NInput v-model:value="model.code" :placeholder="$t('page.login.common.codePlaceholder')" />
|
||||||
<NSpin :show="codeLoading" :size="28" class="h-52px">
|
<NSpin :show="codeLoading" :size="28" class="h-52px">
|
||||||
|
|||||||
@ -29,12 +29,10 @@ import org.dromara.common.sse.dto.SseMessageDto;
|
|||||||
import org.dromara.common.sse.utils.SseMessageUtils;
|
import org.dromara.common.sse.utils.SseMessageUtils;
|
||||||
import org.dromara.common.tenant.helper.TenantHelper;
|
import org.dromara.common.tenant.helper.TenantHelper;
|
||||||
import org.dromara.system.domain.bo.SysTenantBo;
|
import org.dromara.system.domain.bo.SysTenantBo;
|
||||||
|
import org.dromara.system.domain.bo.SysUserBo;
|
||||||
import org.dromara.system.domain.vo.SysClientVo;
|
import org.dromara.system.domain.vo.SysClientVo;
|
||||||
import org.dromara.system.domain.vo.SysTenantVo;
|
import org.dromara.system.domain.vo.SysTenantVo;
|
||||||
import org.dromara.system.service.ISysClientService;
|
import org.dromara.system.service.*;
|
||||||
import org.dromara.system.service.ISysConfigService;
|
|
||||||
import org.dromara.system.service.ISysSocialService;
|
|
||||||
import org.dromara.system.service.ISysTenantService;
|
|
||||||
import org.dromara.web.domain.vo.LoginTenantVo;
|
import org.dromara.web.domain.vo.LoginTenantVo;
|
||||||
import org.dromara.web.domain.vo.LoginVo;
|
import org.dromara.web.domain.vo.LoginVo;
|
||||||
import org.dromara.web.domain.vo.TenantListVo;
|
import org.dromara.web.domain.vo.TenantListVo;
|
||||||
@ -72,6 +70,7 @@ public class AuthController {
|
|||||||
private final ISysSocialService socialUserService;
|
private final ISysSocialService socialUserService;
|
||||||
private final ISysClientService clientService;
|
private final ISysClientService clientService;
|
||||||
private final ScheduledExecutorService scheduledExecutorService;
|
private final ScheduledExecutorService scheduledExecutorService;
|
||||||
|
private final ISysUserService userService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,6 +188,28 @@ public class AuthController {
|
|||||||
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
||||||
return R.fail("当前系统没有开启注册功能!");
|
return R.fail("当前系统没有开启注册功能!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(user.getUserCategory().equals("0")){//注意与字典保持一致
|
||||||
|
if(StringUtils.isBlank(user.getMktNo())){
|
||||||
|
return R.fail("营销人员营销编号不能为空");
|
||||||
|
}
|
||||||
|
if(user.getMktNo().length() != 9){
|
||||||
|
return R.fail("营销编号错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SysUserBo sysUser = new SysUserBo();
|
||||||
|
sysUser.setUserName(user.getUsername());
|
||||||
|
sysUser.setIdCard(user.getIdCard());
|
||||||
|
sysUser.setMktNo(user.getMktNo());
|
||||||
|
if (!userService.checkUserNameUnique(sysUser)) {
|
||||||
|
return R.fail("注册用户'" + user.getUsername() + "'失败,登录账号已存在");
|
||||||
|
}else if (StringUtils.isNotEmpty(user.getIdCard()) && !userService.checkIdCardUnique(sysUser)) {
|
||||||
|
return R.fail("注册用户'" + user.getUsername() + "'失败,身份证号已存在");
|
||||||
|
}else if (StringUtils.isNotEmpty(user.getMktNo()) && !userService.checkMktNoUnique(sysUser)) {
|
||||||
|
return R.fail("注册用户'" + user.getUsername() + "'失败,营销编号已存在");
|
||||||
|
}
|
||||||
|
|
||||||
registerService.register(user);
|
registerService.register(user);
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,10 +54,16 @@ public class SysRegisterService {
|
|||||||
}
|
}
|
||||||
SysUserBo sysUser = new SysUserBo();
|
SysUserBo sysUser = new SysUserBo();
|
||||||
sysUser.setUserName(username);
|
sysUser.setUserName(username);
|
||||||
sysUser.setNickName(username);
|
sysUser.setNickName(registerBody.getNickName());
|
||||||
sysUser.setPassword(BCrypt.hashpw(password));
|
sysUser.setPassword(BCrypt.hashpw(password));
|
||||||
sysUser.setUserType(userType);
|
sysUser.setUserType(userType);
|
||||||
|
|
||||||
|
sysUser.setMktNo(registerBody.getMktNo());
|
||||||
|
sysUser.setDeptId(registerBody.getDeptId());//TODO 部分树按业务需求精简即可,目前是查询出所有供用户选择
|
||||||
|
sysUser.setIdCard(registerBody.getIdCard());
|
||||||
|
sysUser.setUserCategory(registerBody.getUserCategory());
|
||||||
|
sysUser.setRoleIds(new Long[]{1942042655333339137L});//TODO 需要确定注册用户的角色,角色只能固定不能用用户自己选择
|
||||||
|
|
||||||
boolean exist = TenantHelper.dynamic(tenantId, () -> {
|
boolean exist = TenantHelper.dynamic(tenantId, () -> {
|
||||||
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
|
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
|
||||||
.eq(SysUser::getUserName, sysUser.getUserName()));
|
.eq(SysUser::getUserName, sysUser.getUserName()));
|
||||||
|
|||||||
@ -111,6 +111,7 @@ sa-token:
|
|||||||
# security配置
|
# security配置
|
||||||
security:
|
security:
|
||||||
# 排除路径
|
# 排除路径
|
||||||
|
# 开启注册,需要放开部分字典授权
|
||||||
excludes:
|
excludes:
|
||||||
- /*.html
|
- /*.html
|
||||||
- /**/*.html
|
- /**/*.html
|
||||||
@ -121,6 +122,8 @@ security:
|
|||||||
- /*/api-docs
|
- /*/api-docs
|
||||||
- /*/api-docs/**
|
- /*/api-docs/**
|
||||||
- /warm-flow-ui/config
|
- /warm-flow-ui/config
|
||||||
|
- /system/dict/data/type/mps_user_category
|
||||||
|
- /system/user/regDeptTree
|
||||||
|
|
||||||
# 多租户配置
|
# 多租户配置
|
||||||
tenant:
|
tenant:
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package org.dromara.common.core.domain.model;
|
package org.dromara.common.core.domain.model;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.core.xss.Xss;
|
||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,9 +17,10 @@ import org.hibernate.validator.constraints.Length;
|
|||||||
public class RegisterBody extends LoginBody {
|
public class RegisterBody extends LoginBody {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 登录名
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "{user.username.not.blank}")
|
@NotBlank(message = "{user.username.not.blank}")
|
||||||
|
@Xss(message = "用户账号不能包含脚本字符")
|
||||||
@Length(min = 2, max = 30, message = "{user.username.length.valid}")
|
@Length(min = 2, max = 30, message = "{user.username.length.valid}")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@ -30,4 +33,21 @@ public class RegisterBody extends LoginBody {
|
|||||||
|
|
||||||
private String userType;
|
private String userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姓名
|
||||||
|
*/
|
||||||
|
@Xss(message = "用户姓名不能包含脚本字符")
|
||||||
|
@NotBlank(message = "用户姓名不能为空")
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
@NotBlank(message = "身份证号不允许为空")
|
||||||
|
private String idCard;
|
||||||
|
|
||||||
|
private String mktNo;
|
||||||
|
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户类别不允许为空")
|
||||||
|
private String userCategory;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -180,6 +180,15 @@ public class SysUserController extends BaseController {
|
|||||||
return R.fail("新增用户'" + user.getUserName() + "'失败,营销编号已存在");
|
return R.fail("新增用户'" + user.getUserName() + "'失败,营销编号已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(user.getUserCategory().equals("0")){//注意与字典保持一致
|
||||||
|
if(StringUtils.isBlank(user.getMktNo())){
|
||||||
|
return R.fail("营销人员营销编号不能为空");
|
||||||
|
}
|
||||||
|
if(user.getMktNo().length() != 6){
|
||||||
|
return R.fail("营销编号错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 不再校验手机号和邮箱
|
// 不再校验手机号和邮箱
|
||||||
/*else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
|
/*else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
|
||||||
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||||
@ -207,6 +216,7 @@ public class SysUserController extends BaseController {
|
|||||||
userService.checkUserAllowed(user.getUserId());
|
userService.checkUserAllowed(user.getUserId());
|
||||||
userService.checkUserDataScope(user.getUserId());
|
userService.checkUserDataScope(user.getUserId());
|
||||||
deptService.checkDeptDataScope(user.getDeptId());
|
deptService.checkDeptDataScope(user.getDeptId());
|
||||||
|
|
||||||
if (!userService.checkUserNameUnique(user)) {
|
if (!userService.checkUserNameUnique(user)) {
|
||||||
return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||||
}
|
}
|
||||||
@ -216,6 +226,15 @@ public class SysUserController extends BaseController {
|
|||||||
return R.fail("修改用户'" + user.getUserName() + "'失败,营销编号已存在");
|
return R.fail("修改用户'" + user.getUserName() + "'失败,营销编号已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(user.getUserCategory().equals("0")){//注意与字典保持一致
|
||||||
|
if(StringUtils.isBlank(user.getMktNo())){
|
||||||
|
return R.fail("营销人员营销编号不能为空");
|
||||||
|
}
|
||||||
|
if(user.getMktNo().length() != 9){
|
||||||
|
return R.fail("营销编号错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 不再校验手机号和邮箱
|
// 不再校验手机号和邮箱
|
||||||
/*else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
|
/*else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
|
||||||
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||||
@ -320,6 +339,18 @@ public class SysUserController extends BaseController {
|
|||||||
return R.ok(deptService.selectDeptTreeList(dept));
|
return R.ok(deptService.selectDeptTreeList(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册时获取部门树列表
|
||||||
|
*
|
||||||
|
* 之所以单独抽出来是为了区分权限及数据范围@PathVariable("source") String source
|
||||||
|
* 需求确定后,可以通过bo添加过滤条件,暂时还是查询全部
|
||||||
|
*/
|
||||||
|
@GetMapping("/regDeptTree")
|
||||||
|
public R<List<Tree<Long>>> regDeptTree(String tenantId) {
|
||||||
|
System.out.println(tenantId);
|
||||||
|
return R.ok(deptService.selectRegDeptTreeList(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取部门下的所有用户信息
|
* 获取部门下的所有用户信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -78,4 +78,6 @@ public class SysDeptBo extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
private Long belongDeptId;
|
private Long belongDeptId;
|
||||||
|
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,8 +64,6 @@ public class SysUserBo extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* 营销编号
|
* 营销编号
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "营销编号不能为空")
|
|
||||||
@Size(min = 9, max = 9, message = "营销编号长度必须为9位")
|
|
||||||
private String mktNo;
|
private String mktNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -33,6 +33,10 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
|
|||||||
return this.selectVoList(queryWrapper);
|
return this.selectVoList(queryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<SysDeptVo> selectRegDeptList(Wrapper<SysDept> queryWrapper) {
|
||||||
|
return this.selectVoList(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询部门管理数据
|
* 分页查询部门管理数据
|
||||||
*
|
*
|
||||||
|
|||||||
@ -44,6 +44,8 @@ public interface SysRoleMapper extends BaseMapperPlus<SysRole, SysRoleVo> {
|
|||||||
})
|
})
|
||||||
List<SysRoleVo> selectRoleList(@Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
|
List<SysRoleVo> selectRoleList(@Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
|
||||||
|
|
||||||
|
List<SysRoleVo> selectRegRoleList(@Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色ID查询角色信息
|
* 根据角色ID查询角色信息
|
||||||
*
|
*
|
||||||
|
|||||||
@ -40,6 +40,8 @@ public interface ISysDeptService {
|
|||||||
*/
|
*/
|
||||||
List<Tree<Long>> selectDeptTreeList(SysDeptBo dept);
|
List<Tree<Long>> selectDeptTreeList(SysDeptBo dept);
|
||||||
|
|
||||||
|
List<Tree<Long>> selectRegDeptTreeList(String tenantId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建前端所需要下拉树结构
|
* 构建前端所需要下拉树结构
|
||||||
*
|
*
|
||||||
|
|||||||
@ -92,12 +92,21 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
|
|||||||
return buildDeptTreeSelect(depts);
|
return buildDeptTreeSelect(depts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Tree<Long>> selectRegDeptTreeList(String tenantId) {
|
||||||
|
SysDeptBo bo = new SysDeptBo();
|
||||||
|
bo.setTenantId(tenantId);
|
||||||
|
LambdaQueryWrapper<SysDept> lqw = buildQueryWrapper(bo);
|
||||||
|
List<SysDeptVo> depts = baseMapper.selectRegDeptList(lqw);
|
||||||
|
return buildDeptTreeSelect(depts);
|
||||||
|
}
|
||||||
|
|
||||||
private LambdaQueryWrapper<SysDept> buildQueryWrapper(SysDeptBo bo) {
|
private LambdaQueryWrapper<SysDept> buildQueryWrapper(SysDeptBo bo) {
|
||||||
Map<String, Object> params = bo.getParams();
|
Map<String, Object> params = bo.getParams();
|
||||||
LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery();
|
||||||
lqw.eq(SysDept::getDelFlag, SystemConstants.NORMAL);
|
lqw.eq(SysDept::getDelFlag, SystemConstants.NORMAL);
|
||||||
lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId());
|
lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId());
|
||||||
lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId());
|
lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId());
|
||||||
|
lqw.eq(ObjectUtil.isNotNull(bo.getTenantId()), SysDept::getTenantId, bo.getTenantId());
|
||||||
lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName());
|
lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName());
|
||||||
lqw.like(StringUtils.isNotBlank(bo.getDeptCategory()), SysDept::getDeptCategory, bo.getDeptCategory());
|
lqw.like(StringUtils.isNotBlank(bo.getDeptCategory()), SysDept::getDeptCategory, bo.getDeptCategory());
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDept::getStatus, bo.getStatus());
|
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDept::getStatus, bo.getStatus());
|
||||||
|
|||||||
@ -353,13 +353,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public int insertUser(SysUserBo user) {
|
public int insertUser(SysUserBo user) {
|
||||||
System.out.println("user2:" + JSONUtil.toJsonStr(user));
|
|
||||||
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
|
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
|
||||||
System.out.println("user3:" + JSONUtil.toJsonStr(sysUser));
|
|
||||||
// 新增用户信息
|
// 新增用户信息
|
||||||
int rows = baseMapper.insert(sysUser);
|
int rows = baseMapper.insert(sysUser);
|
||||||
user.setUserId(sysUser.getUserId());
|
user.setUserId(sysUser.getUserId());
|
||||||
System.out.println("user4:" + JSONUtil.toJsonStr(user));
|
|
||||||
// 新增用户岗位关联
|
// 新增用户岗位关联
|
||||||
insertUserPost(user, false);
|
insertUserPost(user, false);
|
||||||
// 新增用户与角色管理
|
// 新增用户与角色管理
|
||||||
@ -374,12 +373,24 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public boolean registerUser(SysUserBo user, String tenantId) {
|
public boolean registerUser(SysUserBo user, String tenantId) {
|
||||||
user.setCreateBy(0L);
|
user.setCreateBy(0L);
|
||||||
user.setUpdateBy(0L);
|
user.setUpdateBy(0L);
|
||||||
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
|
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
|
||||||
sysUser.setTenantId(tenantId);
|
sysUser.setTenantId(tenantId);
|
||||||
return baseMapper.insert(sysUser) > 0;
|
//return baseMapper.insert(sysUser) > 0;
|
||||||
|
|
||||||
|
// 新增用户信息
|
||||||
|
int rows = baseMapper.insert(sysUser);
|
||||||
|
user.setUserId(sysUser.getUserId());
|
||||||
|
|
||||||
|
// 新增用户岗位关联
|
||||||
|
//insertUserPost(user, false);
|
||||||
|
// 新增用户与角色管理
|
||||||
|
insertRegUserRole(user, false);
|
||||||
|
|
||||||
|
return rows >0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -490,6 +501,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
|||||||
this.insertUserRole(user.getUserId(), user.getRoleIds(), clear);
|
this.insertUserRole(user.getUserId(), user.getRoleIds(), clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void insertRegUserRole(SysUserBo user, boolean clear) {
|
||||||
|
this.insertRegUserRole(user.getUserId(), user.getRoleIds(), clear);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增用户岗位信息
|
* 新增用户岗位信息
|
||||||
*
|
*
|
||||||
@ -548,6 +563,33 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void insertRegUserRole(Long userId, Long[] roleIds, boolean clear) {
|
||||||
|
if (ArrayUtil.isNotEmpty(roleIds)) {
|
||||||
|
List<Long> roleList = new ArrayList<>(List.of(roleIds));
|
||||||
|
if (!LoginHelper.isSuperAdmin(userId)) {
|
||||||
|
roleList.remove(SystemConstants.SUPER_ADMIN_ID);
|
||||||
|
}
|
||||||
|
// 判断是否具有此角色的操作权限
|
||||||
|
List<SysRoleVo> roles = roleMapper.selectRegRoleList(
|
||||||
|
new QueryWrapper<SysRole>().in("r.role_id", roleList));
|
||||||
|
if (CollUtil.isEmpty(roles)) {
|
||||||
|
throw new ServiceException("没有权限访问角色的数据");
|
||||||
|
}
|
||||||
|
if (clear) {
|
||||||
|
// 删除用户与角色关联
|
||||||
|
userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
|
||||||
|
}
|
||||||
|
// 新增用户与角色管理
|
||||||
|
List<SysUserRole> list = StreamUtils.toList(roleList, roleId -> {
|
||||||
|
SysUserRole ur = new SysUserRole();
|
||||||
|
ur.setUserId(userId);
|
||||||
|
ur.setRoleId(roleId);
|
||||||
|
return ur;
|
||||||
|
});
|
||||||
|
userRoleMapper.insertBatch(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过用户ID删除用户
|
* 通过用户ID删除用户
|
||||||
*
|
*
|
||||||
|
|||||||
@ -35,6 +35,11 @@
|
|||||||
${ew.getCustomSqlSegment}
|
${ew.getCustomSqlSegment}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectRegRoleList" resultMap="SysRoleResult">
|
||||||
|
<include refid="selectRoleVo"/>
|
||||||
|
${ew.getCustomSqlSegment}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectRolePermissionByUserId" parameterType="Long" resultMap="SysRoleResult">
|
<select id="selectRolePermissionByUserId" parameterType="Long" resultMap="SysRoleResult">
|
||||||
<include refid="selectRoleVo"/>
|
<include refid="selectRoleVo"/>
|
||||||
WHERE r.del_flag = '0' and sur.user_id = #{userId}
|
WHERE r.del_flag = '0' and sur.user_id = #{userId}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user