form.view
<template>
<div>
<a-form
:model="form"
ref="formRef"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:rules="rules"
>
<a-form-item
v-for="(item, index) in formData"
:key="index"
v-show="item.show"
:label="item.label"
:name="item.key"
>
<a-input
v-model:value.trim="form[item.key]"
v-if="item.type == 'input'"
:disabled="item.disabled"
></a-input>
<!-- 编码查重开始 -->
<a-input
v-if="item.type == 'inputRepeat'"
@blur="blurRepeatEvent(item)"
@change="changeInputRepeat(item)"
v-model:value.trim="form[item.key]"
:disabled="formTitle.indexOf('修改') > -1"
></a-input>
<div
class="errortip"
v-if="item.type == 'inputRepeat' && item.repeatObj.totalCount > 0"
>
{
{ item.repeatObj.errorMessage }}
</div>
<div
class="helptip"
v-if="item.type == 'inputRepeat' && item.repeatObj?.checked"
>
查重已通过
</div>
<!-- 编码查重结束 -->
<a-textarea
v-model:value.trim="form[item.key]"
autoSize
v-if="item.type == 'textarea'"
:disabled="item.disabled"
@blur="
item.delSpaces
? blurEvent(`${item.key}`)
: () => {
return true;
}
"
></a-textarea>
<!-- 籍贯 -->
<v-distpicker
v-if="item.type == 'space'"
v-model="form[item.key]"
@selected="selected"
hide-area
:province="nativePlace.province"
:city="nativePlace.city"
></v-distpicker>
<a-switch
v-model:checked="form[item.key]"
v-if="item.type == 'switch'"
:disabled="item.disabled"
></a-switch>
<a-date-picker
v-if="item.type == 'datepicker'"
:disabled="item.disabled"
v-model:value="form[item.key]"
/>
<a-input-search
v-if="item.type == 'secretInput'"
v-model:value="form[item.key]"
@search="changeRandom(item.key)"
:disabled="item.disabled"
>
<template #enterButton>
<a-button :disabled="item.disabled">随机生成</a-button>
</template></a-input-search
>
<a-select
v-model:value="form[item.key]"
v-if="item.type == 'select'"
:disabled="item.disabled"
:allowClear="item.allowClear"
:getPopupContainer="(triggerNode) => triggerNode.parentNode"
>
<a-select-option
v-for="selectOption in item.selectList"
:key="selectOption.id"
:value="selectOption.id"
>{
{
selectOption.displayName || selectOption.name
}}</a-select-option
>
</a-select>
<Select
ref="selectRef"
v-if="item.type == 'requestSelect'"
:objectName="item.key"
:popupScroll="item.requestApi"
:watchParams="item.watchParams"
:params="item.requestParams"
:isAffect="item.isAffect"
:allowClear="item.requestAllowClear"
@selectedValue="
(value) => selectedValue(value, item.isAffect, item.key)
"
></Select>
<!-- 用户声明 -->
<div v-if="item.type=='claims'">
<div @click="selectDeclare">
<a-input v-model:value="selectedDeclare"></a-input>
</div>
<div class="modal">
<a-modal
v-model:visible="visibleDeclare"
:centered="true"
:width="700"
:closable="false"
>
<div class="modalBox">
<div class="left">
<div class="leftTitle">选择</div>
<div class="leftList" v-if="leftList.length">
<div
v-for="(item, index) in leftList"
:key="index"
@click="selectEvent(item)"
>
{
{ item.name }}
</div>
</div>
<div class="leftList" v-else>
<!-- <a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /> -->
</div>
</div>
<div class="right">
<div class="leftTitle">已选</div>
<div class="leftList" v-if="selectedList.length">
<div v-for="(item, index) in selectedList" :key="index">
{
{ item.name }}
<close-outlined
@click="delSelectEvent(item)"
style="font-size: 12px; float: right; line-height: 24px"
/>
</div>
</div>
<div class="leftList" v-else>
<!-- <a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /> -->
</div>
</div>
</div>
<template #footer>
<div style="text-align: center">
<a-button @click="() => (visibleDeclare = false)">取消</a-button>
<a-button type="primary" @click="ok">确定</a-button>
</div>
</template>
</a-modal>
</div>
<!-- <selectModal
:handleDelSelect="handleDelSelect"
:selected="Selected"
:visible="visibleDeclare"
:cancel="cancelDeclare"
:ok="ok"
>
<a-list bordered :data-source="selectList" >
<a-list-item
@click="getDeclareData(item)"
slot="renderItem"
slot-scope="item"
style="padding-left: 20px;"
>{
{ item.name }}
</a-list-item>
</a-list>
</selectModal> -->
</div>
</a-form-item>
<div class="btn_box" v-if="showBtnGroup.submitBtn||showBtnGroup.cancelBtn">
<div class="btnGroup">
<a-button
type="primary"
v-show="showBtnGroup.submitBtn"
:loading="loading"
@click="submit"
>提交</a-button
>
<a-button v-show="showBtnGroup.cancelBtn" @click="cancel"
>取消</a-button
>
</div>
</div>
</a-form>
</div>
</template>
<script setup>
import moment from "moment";
import selectModal from '@/components/selectModal/index.vue'
import { getResource, getCurResource } from "@/api/resourceApi";
import { getUserfield } from "@/api/userfieldApi";
import VDistpicker from "v-distpicker";
import { reactive, ref, watch, onMounted, nextTick, computed } from "vue";
import { message } from "ant-design-vue";
import Select from "@/components/Select/index.vue";
import { useRoute } from "vue-router";
import {getRandom}from '@/utils/globalFunc'
const route = useRoute();
// 表单
let form = reactive({});
// 表单的ref
const formRef = ref();
// 表单样式
const labelCol = { span: 6 };
const wrapperCol = { span: 14 };
// 父组件传递的参数
const props = defineProps({
curRoleID: {
type: String,
default: "",
},
roleId: {
type: String,
default: "",
},
// 传递表单数据
formData: {
type: Array,
default: () => {
return [
{
key: "name", // 字段名(必填)
value: "", //字段默认值(必填)
label: "日志集名称", // 字段label名(必填)
repeatObj: {
validatorPass: false,
checked: false,
totalCount: 0,
errorMessage: "",
}, //查重必传属性
rulesObj: {
rule: [{ required: true, message: "名称为必填项" }],
validate: null, //() => {}
validataTrigger: "", //change/blur
},
type: "input", // 输入类型(必填)('input','select','inputRepeat(需要查重时使用)','textarea','switch','requestSelect(下拉列表需要滚动请求)',)
delSpaces: false, // 'input', 'textarea'时,如果值中包含空格,失去焦点时自动去除
show: true, // 该输入框是否展示(必填)
disabled: false, // 输入框是否禁用(必填)
selectList: [], // 类型为'select'必填
allowClear: false, // 类型为'select'时,是否允许清除
requestApi: () => {}, // 'requestSelect'时,请求接口
requestAllowClear: false, // 'requestSelect'时,是否允许清除
watchParams: true, // 'requestSelect'时,是否请求的监听参数
requestParams: {}, // 'requestSelect'时,请求接口参数
isAffect: true, // 'requestSelect'时,选值时是否影响其他requestSelect的选择
},
];
},
},
showBtnGroup: {
type: Object,
default: {
submitBtn: true, // 提交按钮是否展示
cancelBtn: true, // 取消按钮是否展示
},
},
// 添加调用的接口
addApi: {
type: Function,
default: () => {},
},
// 添加权限组调用的接口
addGroupApi: {
type: Function,
default: () => {},
},
// 修改调用的接口closeForm
editApi: {
type: Function,
default: () => {},
},
// 提交成功后刷新页面方法
refreshFunc: {
type: Function,
default: () => {},
},
// 表单标题
formTitle: {
type: String,
default: "",
},
// 关闭表单方法
closeForm: {
type: Function,
default: () => {},
},
// 添加权限组成功后的回调
childrenTable: {
type: Function,
default: () => {},
},
// 监听参数(是否打开表单)
visible: {
type: Boolean,
default: false,
},
// 被控制/被影响的其他请求下拉框
controlledSelect: {
type: Function,
default: () => {},
},
//用户管理列表修改、添加时,自定义字段的接口
addCustomizeApi: {
type: Function,
default: () => {},
},
editCustomizeApi: {
type: Function,
default: () => {},
},
selectResourceCount: {
type: Number,
default: 0,
},
selectScopeCount: {
type: Number,
default: 0,
},
});
onMounted(() => {
// console.log('1',props.selectResourceCount)
});
// 请求下拉框的ref
const selectRef = ref(null);
// 防抖
let loading = ref(false);
let rules = ref({});
const getRules = () => {
props.formData.forEach((item) => {
rules.value[item.key] = item.rulesObj
? [
...item.rulesObj.rule,
{
validator: async (rule, value) => {
if (value) {
if (item.rulesObj.validate) {
const { success, message } = await item.rulesObj.validate(
value,
item
);
if (success) {
return Promise.resolve();
} else {
return Promise.reject(message);
}
} else {
return Promise.resolve();
}
}
},
trigger: item.rulesObj.validataTrigger
? item.rulesObj.validataTrigger
: ["change", "blur"],
},
]
: [];
});
};
// 查重
const blurRepeatEvent = (item) => {
if (item.repeatObj.validatorPass) {
item
.requestApi({ ...item.requestParams, code: form[item.key] })
.then((res) => {
if (res.totalCount > 0) {
if (
props.formTitle.indexOf("修改") > -1 &&
item.value == form[item.key]
) {
item.repeatObj.checked = true;
} else {
item.repeatObj.checked = false;
item.repeatObj.totalCount = res.totalCount;
}
} else {
item.repeatObj.checked = true;
console.log('value',form[item.key])
}
})
.catch((err) => {
console.log("err", err);
});
}
};
function changeInputRepeat(item) {
item.repeatObj.totalCount = 0;
item.repeatObj.checked = false;
}
// 查重校验是否可提交
let isSubmit = ref(true);
// 校验
// 查重校验
async function checkCode(_rule, value) {
const reg = /[^\x21-\x7E]+/g;
isTrue.value = false;
// showhelp.value = false;
if (codeDuplicate.value == 0) {
if (value && reg.test(value)) {
return Promise.reject(
"只允许大写字母、小写字母、数字和特殊符号(除空格)"
);
} else if (value && value.length > 18) {
return Promise.reject(`输入字符不能超过18`);
} else {
isSubmit.value = true;
isTrue.value = true;
return Promise.resolve();
}
} else {
isSubmit.value = false;
codeDuplicate.value = 0;
return Promise.reject(`该编码已被占用,请重新输入`);
}
}
// input框失去焦点时,去除空格
function blurEvent(params) {
// var reg = /\s+/g;
form[params] = form[params].trim();
formRef.value.validate(`${params}`);
}
// checkName校验
async function checkName(_rule, value) {
var reg = /\s+/g;
const maxLength = _rule.field == "code" ? 18 : 20;
if (value && value.length > maxLength) {
return Promise.reject(`输入字符不能超过${maxLength}`);
} else if (reg.test(value)) {
return Promise.reject("不允许输入空格");
} else {
return Promise.resolve();
}
}
// 不做校验
async function checkNo() {
return Promise.resolve();
}
// 随机生成按钮
function changeRandom(value) {
form[value] = getRandom();
formRef.value.validate(`${value}`);
}
// 校验密码
async function checkSecret(_rule, value) {
const rules = /^[0-9a-zA-Z]*$/g;
if (rules.test(value)) {
return Promise.resolve();
}
return Promise.reject("只允许输入数字和字母");
}
let nativePlace = reactive({
provice: "",
city: "",
});
// 提交
function submit() {
// 是否做查重:isRepeatInput为true需要做查重,否则不做
let isRepeatInput = true;
props.formData.forEach((item) => {
if (item.repeatObj && item.repeatObj.totalCount > 0) {
repeat = false;
}
});
if (isRepeatInput) {
formRef.value
.validate()
.then((res) => {
loading.value = true;
if (props.formTitle.indexOf("添加权限组用户") > -1) {
props
.addApi({
roleGroupId: props.curRoleID,
userId: form.userId,
type: form.type,
})
.then((res) => {
message.success("添加权限组用户成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
else if (props.formTitle.indexOf("添加权限用户") > -1) {
props
.addApi({
roleId: props.roleId,
ordinal: 0,
// ...form,
type:form.type,
userId:form.userId
})
.then((res) => {
message.success("添加权限用户成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
else if (props.formTitle.indexOf("添加权限组") > -1) {
props
.addGroupApi({
roleGroupId: form.roleGroupId,
roleId: form.roleID,
ordinal: 0,
...form,
})
.then((res) => {
message.success("添加权限组成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
else if (props.formTitle.indexOf("添加权限") > -1) {
if (route.fullPath == "/appConfig/powerManage/powerAssign"){
props
.addApi({
roleGroupId: props.curRoleID,
roleId: form.name,
ordinal: 0,
})
.then((res) => {
message.success("添加权限成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
else if(route.fullPath == "/appConfig/powerManage/powerList"){
props
.addApi({ ...form })
.then((res) => {
message.success("添加成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
}
else if (props.formTitle.indexOf("添加") > -1) {
const apiScopeClaims = selectedList.value.map(item => {
delete item.name
return item
})
props
.addApi({ ...form,apiScopeClaims: JSON.parse(JSON.stringify(apiScopeClaims).replace(/value/g, 'type')) })
.then((res) => {
message.success("添加成功");
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
} else if (props.formTitle.indexOf("修改") > -1) {
props
.editApi({ ...form }, form.id)
.then((res) => {
props.refreshFunc();
cancel();
props.closeForm();
})
.catch((err) => {
loading.value = false;
});
}
})
.catch((err) => {
message.warning("请输入/选择必填项");
});
}
}
// 取消
function cancel() {
loading.value = false;
formRef.value.resetFields();
props.closeForm();
nativePlace = {
provice: "",
city: "",
};
}
// select组件调用的方法(params子组件中传递的值,isAffect是否影响其他请求下拉框)
function selectedValue(params, isAffect, key) {
// form[params.key] = params.value;
// nextTick(() => {
// formRef.value.validate(`${params.key}`);
// });
// if (isAffect) {
// // 影响作用请求下拉框选中数据改变,被影响请求下拉框值清空
// props.controlledSelect(form);
// if (selectRef.value[1]) {
// selectRef.value[1].delSelectedData();
// }
// }
form[params.key] = params.value;
nextTick(() => {
formRef.value.validate(`${params.key}`);
});
if (props.formTitle == "添加权限" && isAffect) {
if (key == "scopeId") {
getResource({
Enabled: true,
MaxResultCount: 15,
PageNumber: 1,
ApiScopeId: form.scopeId,
}).then((res) => {
if (res.items) {
selectRef.value[1].selectList = res.items;
selectRef.value[1].selectedData = "";
}
});
props.formData[2].selectList.splice(0);
form.name = "";
form.apiResourceId = "";
} else if (key == "apiResourceId") {
getCurResource({ id: form.apiResourceId }).then((res) => {
if (res.roles) {
props.formData[2].selectList = res.roles;
form.name = "";
}
});
}
}
}
//用户声明相关的方法和变量
const Selected=ref([])
const selectedData1=ref([])
const selectList=ref([])
const oldName=ref('')
// 用户声明的input框
const selectedDeclare1=ref('')
// 用户声明的弹窗框的显示
const visibleDeclare=ref(false)
// 用户声明的弹出框的可选择的列表数据
const selectDeclareList=ref([
{ name: '用户资料', value: 'profile' },
{ name: '唯一标识', value: 'sub' },
{ name: '姓名', value: 'name' },
{ name: '昵称', value: 'nickname' },
{ name: '性别', value: 'gender' },
{ name: '头像', value: 'picture' },
{ name: '生日', value: 'birthdate' },
{ name: '时区', value: 'zoneinfo' },
{ name: '区域', value: 'locale' },
{ name: '地址', value: 'address' },
{ name: '权限', value: 'role' },
{ name: '邮箱', value: 'email' },
{ name: '邮箱验证', value: 'email_verified' },
{ name: '电话号', value: 'phone_number' },
{ name: '电话号验证', value: 'phone_number_verified' },
{ name: '企业ID', value: 'EnterpriseId' },
{ name: '企业名称', value: 'EnterpriseName' },
{ name: '地区', value: 'NativePlace' }
])
// 弹出框显示出来
function selectDeclare1() {
// Selected.value = selectedData.value
// const selected = Selected.value.map(item => item.value)
// selectList.value = selectDeclareList.value.filter(item => !selected.includes(item.value))
visibleDeclare.value = true
}
// 删除弹窗框中选中的值
function handleDelSelect(index){
Selected.value.splice(index, 1)
const selected = selected.value.map(item => item.value)
selectList.value = selectDeclareList.value.filter(item => !selected.includes(item.value))
}
// 关闭弹出框
function cancelDeclare(){
// this.selected = []
visibleDeclare.value = false
}
// 选中数据值关闭弹出框
function ok1(){
visibleDeclare.value = false
selectedData.value = Selected.value
if (selectedData.value.length > 0) {
for (var i = 0; i < selectedData.value.length; i++) {
if (i == 0) {
selectedDeclare.value = selectedData.value[i].name
} else {
selectedDeclare.value = selectedDeclare.value + ',' + selectedData.value[i].name
}
}
} else {
selectedDeclare.value = ''
}
}
function getData(){
detailApiScope(this.id).then(res => {
// 用户声明
for (var i = 0; i < res.apiScopeClaims.length; i++) {
if (i == 0) {
selectedDeclare.value = selectList.value.find(item => {
return item.value == res.apiScopeClaims[0].type
}).name
} else {
selectedDeclare.value =
selectedDeclare.value +
',' +
selectList.value.find(item => {
return item.value == res.apiScopeClaims[i].type
}).name
}
selectedData.value[i] = {
value: res.apiScopeClaims[i].type,
name: selectList.value.find(item => {
return item.value == res.apiScopeClaims[i].type
}).name
}
}
Selected.value = [...selectedData.value]
oldName.value = res.name
const apiScopeClaims = res.apiScopeClaims.map(item => item.type)
selectList.value = selectList.value.filter(item => !apiScopeClaims.includes(item.value))
apiScopeForm.value = {
id: this.id,
name: res.name,
displayName: res.displayName,
enabled: res.enabled,
showInDiscoveryDocument: res.showInDiscoveryDocument,
required: res.required,
emphasize: res.emphasize,
description: res.description
}
})
}
// 后来换的
const selectedData=ref([])
const selectedList = ref([]);
// 用户声明的input框
const selectedDeclare=ref('')
function selectDeclare() {
// Selected.value = selectedData.value
// const selected = Selected.value.map(item => item.value)
// selectList.value = selectDeclareList.value.filter(item => !selected.includes(item.value))
visibleDeclare.value = true
}
const leftList = ref([
{ name: '用户资料', value: 'profile' },
{ name: '唯一标识', value: 'sub' },
{ name: '姓名', value: 'name' },
{ name: '昵称', value: 'nickname' },
{ name: '性别', value: 'gender' },
{ name: '头像', value: 'picture' },
{ name: '生日', value: 'birthdate' },
{ name: '时区', value: 'zoneinfo' },
{ name: '区域', value: 'locale' },
{ name: '地址', value: 'address' },
{ name: '权限', value: 'role' },
{ name: '邮箱', value: 'email' },
{ name: '邮箱验证', value: 'email_verified' },
{ name: '电话号', value: 'phone_number' },
{ name: '电话号验证', value: 'phone_number_verified' },
{ name: '企业ID', value: 'EnterpriseId' },
{ name: '企业名称', value: 'EnterpriseName' },
{ name: '地区', value: 'NativePlace' }
]);
const selectEvent = (value) => {
const index = leftList.value.findIndex((item) => item.name == value.name);
leftList.value.splice(index, 1);
selectedList.value.push({ name: value.name,type:value.value });
};
const delSelectEvent = (value) => {
const index = selectedList.value.findIndex(
(item) => item.name == value.name
);
selectedList.value.splice(index, 1);
leftList.value.push({ name: value.name,type:value.value });
};
// 选中数据值关闭弹出框
function ok(){
visibleDeclare.value = false
selectedData.value = selectedList.value
if (selectedData.value.length > 0) {
for (var i = 0; i < selectedData.value.length; i++) {
if (i == 0) {
selectedDeclare.value = selectedData.value[i].name
} else {
selectedDeclare.value = selectedDeclare.value + ',' + selectedData.value[i].name
}
}
} else {
selectedDeclare.value = ''
}
}
// 暴露给父组件的数据
defineExpose({
form,
cancel,
});
// 监听visible
// watch(
// () => visibleDeclare.value,
// (newVal, oldVal) => {
// if(newVal){
// // selectList.value = selectDeclareList.value
// // // console.log('list',selectList.value)
// // if (props.curRoleID) {
// // getData()
// // }
// }
// },
// { deep: true, immediate: true }
// )
watch(
() => props.visible,
(newVal, oldVal) => {
// showhelp.value = false;
// 展示表单时
if (newVal) {
getRules();
} else {
// formRef.value.resetFields();
// 关闭表单时
if (formRef.value) {
formRef.value.resetFields();
props.closeForm();
nativePlace = {
provice: "",
city: "",
};
if (selectRef.value) {
selectRef.value.forEach((item) => {
item.delSelectedData();
});
}
}
}
},
{ deep: true, immediate: true }
);
watch(
() => props.formData,
(newVal, oldVal) => {
// 展示表单时
if (newVal) {
newVal.map((item) => {
if(item.key=='nativePlace'&&item.value){
nativePlace.province = item.value.split(",")[0];
nativePlace.city = item.value.split(",")[1];
form[item.key] = item.value
}
else{
form[item.key] = item.value;
}
});
}
},
{ deep: true, immediate: true }
);
// 籍贯
function selected(info) {
form.nativePlace = info.province.value + "," + info.city.value;
nativePlace = {
province: info.province.value,
city: info.city.value,
};
}
watch(
() => props.roleId,
(newVal, oldVal) => {
props.roleId=newVal
},
)
</script>
<style lang="less" scoped>
.btn_box {
width: 650px;
padding-top: 20px;
padding-bottom: 10px;
border-top: solid 1px #e8e8e8;
position: absolute;
bottom: 0;
right: 0;
text-align: center;
z-index: 2;
background: #fff;
}
.btnGroup {
width: 146px;
display: flex;
justify-content: space-between;
margin: 0 auto;
}
// 查重样式
.checkDuplicate {
position: absolute;
width: 30px;
font-size: 12px;
margin-left: 5px;
line-height: 32px;
}
.helptip {
color: #52c41a;
font-size: 13px;
}
</style>
<style lang="less" scoped>
:deep(.ant-list-items){
height: 376px;
overflow-y: scroll;
cursor: pointer;
}
.add-form-warp {
background-color: #fff;
.addSource {
border: solid 1px #ccc;
border-radius: 5px;
width: 1000px;
margin-left: auto;
margin-right: auto;
}
.showSource {
margin-top: 20px;
width: 1000px;
margin-left: auto;
margin-right: auto;
border: solid 1px #ccc;
border-radius: 5px;
:deep(.ant-table-pagination.ant-pagination) {
margin-right: 20px;
}
}
.title {
line-height: 50px;
border-bottom: solid 1px #ccc;
background-color: rgba(0, 0, 0, 0.03);
margin-bottom: 20px;
div {
margin-left: 20px;
}
}
.picker {
margin-top: 20px;
}
}
</style>
<style lang="less" scoped>
.clientPage {
background-color: #fff;
padding: 24px;
min-height: calc(100vh - 100px);
.basicBox {
margin: 20px auto;
}
.appAuthorBox {
margin: 20px auto;
display: flex;
justify-content: space-between;
.sourceBox {
width: 48%;
:deep(.ant-btn) {
width: 100%;
}
}
.empowerBox {
width: 48%;
:deep(.ant-btn) {
width: 100%;
}
}
}
.secretBox {
width: 80%;
margin: 20px auto;
button {
width: 100%;
}
}
.tokenBox {
width: 80%;
margin: 20px auto;
// text-align: center;
.declareBox {
margin: 20px auto;
.declareBtn {
width: 100%;
}
}
}
}
.modalBox {
display: flex;
justify-content: space-between;
// height: 480px;
.leftTitle {
font-size: 16px;
color: #363636;
padding-bottom: 14px;
}
.leftList {
width: 300px;
height: 380px;
background-color: #f4f6f8;
border: 1px solid #dedede;
border-radius: 5px;
overflow-y: auto;
list-style: none;
div {
width: 100%;
padding: 10px 20px;
border-bottom: 1px solid #e8e8e8;
cursor: pointer;
&:last-child {
border-bottom: none;
}
}
}
}
:deep(.ant-modal-footer) {
text-align: center !important;
}
</style>
select component
<template>
<div class="selectBox">
<a-select
@change="changeSelect"
:getPopupContainer="(triggerNode) => triggerNode.parentNode"
@popupScroll="popupScrollEvent"
v-model:value="selectedData"
@click="focusSelect"
>
<a-select-option
v-for="(item, index) in selectList"
:key="index"
:value="item.id ? item.id : item.logSetId"
>{
{ item.name }}</a-select-option
>
<template #dropdownRender="{ menuNode: menu }">
<v-nodes :vnodes="menu" />
<div v-if="isLoading">
<span><a-spin /></span>
</div>
<div v-else-if="!isNewData" class="noMore">
没有更多数据了
<!-- <template #description> 暂无数据 </template> -->
</div>
<!--显示结果-->
<!--v-nodes必须要写在最后面,这个代表要渲染的下拉列表数据-->
<!-- <template v-else>
<v-nodes :vnodes="menu" />
</template> -->
</template>
</a-select>
</div>
</template>
<script setup>
import { onMounted, ref, watch } from "vue";
import { message } from "ant-design-vue";
import { useRoute } from "vue-router";
const emit = defineEmits();
//必须要写
const VNodes = (_, { attrs }) => {
return attrs.vnodes;
};
const props = defineProps({
// 默认选中数据
value: {
type: String,
default: "",
},
// 监听参数
watchParams: {
type: Boolean,
default: false,
},
// 滚动触底请求接口
popupScroll: {
type: Function,
default: () => {},
},
// 对象键名
objectName: {
type: String,
default: "",
},
// 请求参数
params: {
type: Object,
default: () => {
return {};
},
},
// 表单标题 下拉框内容有时候需要特殊判断特殊处理
formTitle: {
type: String,
default: "",
},
});
let selectList = ref([]);
let PageNumber = ref(1);
const MaxResultCount = ref(10);
let totalPages = ref(1);
// 选中的值
let selectedData = ref("");
onMounted(() => {});
// 是否正在请求中
let isLoading = ref(true);
// 接口请求的新数据
let isNewData = ref(true);
// 滚动事件
function popupScrollEvent(e) {
const { target } = e;
const scrllHeight = target.scrollHeight - target.scrollTop;
const clientHeight = target.clientHeight;
isNewData.value = true;
// 下拉框不下拉的时候
if (scrllHeight === 0 && clientHeight === 0) {
PageNumber.value = 1;
} else if (scrllHeight - clientHeight == 0) {
// 下拉到底部时
if (PageNumber.value < totalPages.value) {
// 如果滑到底部,则加载下一页
PageNumber.value++;
getListDataCode();
} else {
// message.warn("没有更多数据了");
isNewData.value = false;
}
}
}
// 选中的select的值,调用父组件中selectedValue方法
function changeSelect(val) {
const params = {
key: props.objectName,
value: val,
};
selectedData.value = val;
emit("selectedValue", params);
}
// 清空select中的数据
const delSelectedData = () => {
selectedData.value = undefined;
selectList.value = []
};
// 请求方法
function getListDataCode() {
isLoading.value = true;
props
.popupScroll({
PageNumber: PageNumber.value,
MaxResultCount: MaxResultCount.value,
...props.params,
})
.then((res) => {
isLoading.value = false;
//需要特殊显示形势的判断 不需要就删除此判断
if(route.fullPath == "/appConfig/powerManage/powerAssign"){
if(props.formTitle=='添加权限用户'||props.formTitle=='添加权限组用户')
res.items.forEach((item)=>{
item.name=item.disPlayName + '(' + item.name + ')'
})
}
if(route.fullPath == "/organizationManage/archite"){
if(props.formTitle=='添加成员')
res.items.forEach((item)=>{
item.name=item.disPlayName + '(' + item.name + ')'
})
}
selectList.value = selectList.value.concat(res.items ? res.items : res);
totalPages.value = Math.ceil(res.totalCount / MaxResultCount.value);
})
.catch((err) => {
isLoading.value = false;
});
}
// 获取焦点时滚动条回到顶部
function focusSelect() {
if (!selectedData.value) {
document.getElementsByClassName("rc-virtual-list-holder")[0].scrollTop = 0;
}
}
const route = useRoute();
defineExpose({
delSelectedData,
selectedData,
selectList
});
watch(
() => props.watchParams,
(newVal, oldVal) => {
PageNumber.value = 1;
selectList.value = [];
getListDataCode();
selectedData.value = props.value;
// if(props.formTitle=='添加成员'&&props.objectName=='code'){
// PageNumber.value = 1;
// }
// else{
// PageNumber.value = 1;
// selectList.value = [];
// getListDataCode();
// selectedData.value = props.value;
// }
},
{ deep: true, immediate: true }
);
</script>
<style lang="less">
.noMore {
text-align: center;
}
</style>
golalFuc
export function getRandom(length) {
var str = "",
range = length?length: 16,
arr = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
// 随机产生
for (var i = 0; i < range; i++) {
str += arr[Math.round(Math.random() * (arr.length - 1))];
}
return str
}