feat(projects): 新增项目、执行、任务等功能
This commit is contained in:
@@ -298,6 +298,14 @@ async function handleSearchDictType() {
|
||||
await getDictTypeList();
|
||||
}
|
||||
|
||||
async function resetDictTypeSearchParams() {
|
||||
const pageSize = dictTypeSearchParams.pageSize;
|
||||
|
||||
Object.assign(dictTypeSearchParams, getInitDictTypeSearchParams(), { pageSize });
|
||||
|
||||
await getDictTypeList();
|
||||
}
|
||||
|
||||
async function handleSearchDictData() {
|
||||
dictDataSearchParams.pageNo = 1;
|
||||
await getDictDataByPage(1);
|
||||
@@ -349,7 +357,11 @@ onMounted(() => {
|
||||
class="min-h-560px gap-16px overflow-hidden xl:grid xl:grid-cols-[360px_minmax(0,1fr)] lt-xl:flex lt-xl:flex-col lt-xl:overflow-auto"
|
||||
>
|
||||
<div class="flex-col-stretch gap-16px xl:min-h-0">
|
||||
<DictTypeSearch v-model:model="dictTypeSearchParams" @search="handleSearchDictType" />
|
||||
<DictTypeSearch
|
||||
v-model:model="dictTypeSearchParams"
|
||||
@reset="resetDictTypeSearchParams"
|
||||
@search="handleSearchDictType"
|
||||
/>
|
||||
<ElCard v-loading="typeLoading" class="card-wrapper xl:flex-1-hidden" body-class="dict-type-card-body">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between gap-12px py-2px">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { dictStatusOptions } from '@/constants/business';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
import TableSearchFields, { type SearchField } from '@/components/custom/table-search-fields.vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'DictDataSearch' });
|
||||
@@ -9,7 +10,7 @@ interface Props {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
disabled: false
|
||||
});
|
||||
|
||||
@@ -22,6 +23,25 @@ const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<Api.Dict.DictDataSearchParams>('model', { required: true });
|
||||
|
||||
const fields = computed<SearchField[]>(() => [
|
||||
{
|
||||
key: 'label',
|
||||
label: $t('page.system.dict.dictLabel'),
|
||||
type: 'input',
|
||||
placeholder: $t('page.system.dict.form.dictLabel')
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: $t('page.system.dict.dictStatus'),
|
||||
type: 'select',
|
||||
placeholder: $t('page.system.dict.form.dictStatus'),
|
||||
options: dictStatusOptions.map(item => ({
|
||||
label: $t(item.label),
|
||||
value: item.value
|
||||
}))
|
||||
}
|
||||
]);
|
||||
|
||||
function handleReset() {
|
||||
emit('reset');
|
||||
}
|
||||
@@ -32,37 +52,12 @@ function handleSearch() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel
|
||||
:model="model"
|
||||
:disabled="disabled"
|
||||
:action-col-lg="12"
|
||||
:action-col-md="8"
|
||||
<TableSearchFields
|
||||
v-model="model"
|
||||
:fields="fields"
|
||||
:columns="3"
|
||||
:disabled="props.disabled"
|
||||
@reset="handleReset"
|
||||
@search="handleSearch"
|
||||
>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.dict.dictLabel')" prop="label">
|
||||
<ElInput
|
||||
v-model="model.label"
|
||||
clearable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.dict.form.dictLabel')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.dict.dictStatus')" prop="status">
|
||||
<ElSelect
|
||||
v-model="model.status"
|
||||
clearable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.dict.form.dictStatus')"
|
||||
>
|
||||
<ElOption v-for="{ label, value } in dictStatusOptions" :key="value" :label="$t(label)" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -106,8 +106,6 @@ const title = computed(() => {
|
||||
return titleMap[props.operateType];
|
||||
});
|
||||
|
||||
const dialogWidth = '780px';
|
||||
|
||||
const model = ref(createDefaultModel());
|
||||
|
||||
function getCurrentScopeParams(): Api.SystemManage.ScopeQueryParams {
|
||||
@@ -1163,7 +1161,7 @@ watch(visible, value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
:width="dialogWidth"
|
||||
preset="lg"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
@confirm="handleSubmit"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { commonStatusOptions } from '@/constants/business';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
import TableSearchFields, { type SearchField } from '@/components/custom/table-search-fields.vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'MenuSearch' });
|
||||
@@ -22,6 +23,25 @@ const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<Api.SystemManage.MenuSearchParams>('model', { required: true });
|
||||
|
||||
const fields = computed<SearchField[]>(() => [
|
||||
{
|
||||
key: 'name',
|
||||
label: $t('page.system.menu.menuName'),
|
||||
type: 'input',
|
||||
placeholder: $t('page.system.menu.form.menuName')
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: $t('page.system.menu.menuStatus'),
|
||||
type: 'select',
|
||||
placeholder: $t('page.system.menu.form.menuStatus'),
|
||||
options: commonStatusOptions.map(item => ({
|
||||
label: $t(item.label),
|
||||
value: item.value
|
||||
}))
|
||||
}
|
||||
]);
|
||||
|
||||
function reset() {
|
||||
emit('reset');
|
||||
}
|
||||
@@ -32,27 +52,14 @@ function search() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel
|
||||
:model="model"
|
||||
<TableSearchFields
|
||||
v-model="model"
|
||||
:fields="fields"
|
||||
:columns="4"
|
||||
:disabled="props.disabled"
|
||||
:action-col-lg="8"
|
||||
:action-col-md="24"
|
||||
@reset="reset"
|
||||
@search="search"
|
||||
>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.menu.menuName')" prop="name">
|
||||
<ElInput v-model="model.name" clearable :placeholder="$t('page.system.menu.form.menuName')" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.menu.menuStatus')" prop="status">
|
||||
<ElSelect v-model="model.status" clearable class="w-full" :placeholder="$t('page.system.menu.form.menuStatus')">
|
||||
<ElOption v-for="{ label, value } in commonStatusOptions" :key="value" :label="$t(label)" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { postTypeOptions } from '@/constants/business';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
import TableSearchFields, { type SearchField } from '@/components/custom/table-search-fields.vue';
|
||||
|
||||
defineOptions({ name: 'PostSearch' });
|
||||
|
||||
@@ -17,17 +17,69 @@ const statusOptions = [
|
||||
{ label: '停用', value: 1 as const }
|
||||
];
|
||||
|
||||
const keyword = computed({
|
||||
get() {
|
||||
return model.value.name ?? model.value.code ?? '';
|
||||
},
|
||||
set(value: string) {
|
||||
const text = value.trim() || undefined;
|
||||
model.value.name = text;
|
||||
model.value.code = text;
|
||||
}
|
||||
const searchModel = reactive<{
|
||||
keyword: string;
|
||||
postType?: Api.SystemManage.PostType | null;
|
||||
status?: Api.SystemManage.CommonStatus;
|
||||
}>({
|
||||
keyword: '',
|
||||
postType: undefined,
|
||||
status: undefined
|
||||
});
|
||||
|
||||
let syncingFromSource = false;
|
||||
|
||||
watch(
|
||||
() => [model.value.name, model.value.code, model.value.postType, model.value.status] as const,
|
||||
([name, code, postType, status]) => {
|
||||
syncingFromSource = true;
|
||||
searchModel.keyword = name ?? code ?? '';
|
||||
searchModel.postType = postType;
|
||||
searchModel.status = status;
|
||||
syncingFromSource = false;
|
||||
},
|
||||
{ immediate: true, flush: 'sync' }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => [searchModel.keyword, searchModel.postType, searchModel.status] as const,
|
||||
([keywordValue, postType, status]) => {
|
||||
if (syncingFromSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keywordText = keywordValue.trim() || undefined;
|
||||
model.value.name = keywordText;
|
||||
model.value.code = keywordText;
|
||||
model.value.postType = postType;
|
||||
model.value.status = status;
|
||||
},
|
||||
{ flush: 'sync' }
|
||||
);
|
||||
|
||||
const fields = computed<SearchField[]>(() => [
|
||||
{
|
||||
key: 'keyword',
|
||||
label: '岗位名称',
|
||||
type: 'input',
|
||||
placeholder: '请输入岗位名称或岗位编码'
|
||||
},
|
||||
{
|
||||
key: 'postType',
|
||||
label: '岗位类型',
|
||||
type: 'select',
|
||||
placeholder: '请选择岗位类型',
|
||||
options: postTypeOptions
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: '岗位状态',
|
||||
type: 'select',
|
||||
placeholder: '请选择岗位状态',
|
||||
options: statusOptions
|
||||
}
|
||||
]);
|
||||
|
||||
function reset() {
|
||||
emit('reset');
|
||||
}
|
||||
@@ -38,27 +90,7 @@ function search() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel :model="model" :action-col-lg="8" @reset="reset" @search="search">
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位名称" prop="name">
|
||||
<ElInput v-model="keyword" clearable placeholder="请输入岗位名称或岗位编码" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位类型" prop="postType">
|
||||
<ElSelect v-model="model.postType" clearable placeholder="请选择岗位类型">
|
||||
<ElOption v-for="{ label, value } in postTypeOptions" :key="value" :label="label" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位状态" prop="status">
|
||||
<ElSelect v-model="model.status" clearable placeholder="请选择岗位状态">
|
||||
<ElOption v-for="{ label, value } in statusOptions" :key="value" :label="label" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
<TableSearchFields v-model="searchModel" :fields="fields" :columns="4" @reset="reset" @search="search" />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -429,10 +429,6 @@ getMenuTreeData();
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-row) {
|
||||
margin: 0 0 -15px 0;
|
||||
}
|
||||
|
||||
.role-card-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
@@ -167,24 +167,25 @@ watch(visible, value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
preset="sm"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
:scrollbar="false"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.role.roleName')" prop="name">
|
||||
<ElInput v-model="model.name" :placeholder="$t('page.system.role.form.roleName')" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.role.roleCode')" prop="code">
|
||||
<ElInput v-model="model.code" :placeholder="$t('page.system.role.form.roleCode')" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.role.sort')" prop="sort">
|
||||
<ElInputNumber
|
||||
v-model="model.sort"
|
||||
@@ -194,7 +195,7 @@ watch(visible, value => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.role.roleStatus')" prop="status">
|
||||
<ElRadioGroup v-model="model.status" class="business-form-radio-group">
|
||||
<ElRadio v-for="{ label, value } in commonStatusOptions" :key="value" :value="value">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { commonStatusOptions } from '@/constants/business';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
import TableSearchFields, { type SearchField } from '@/components/custom/table-search-fields.vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'RoleSearch' });
|
||||
@@ -15,17 +15,61 @@ const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<Api.SystemManage.RoleSearchParams>('model', { required: true });
|
||||
|
||||
const keyword = computed({
|
||||
get() {
|
||||
return model.value.name ?? model.value.code ?? '';
|
||||
},
|
||||
set(value: string) {
|
||||
const text = value.trim() || undefined;
|
||||
model.value.name = text;
|
||||
model.value.code = text;
|
||||
}
|
||||
const searchModel = reactive<{
|
||||
keyword: string;
|
||||
status?: Api.SystemManage.CommonStatus;
|
||||
}>({
|
||||
keyword: '',
|
||||
status: undefined
|
||||
});
|
||||
|
||||
let syncingFromSource = false;
|
||||
|
||||
watch(
|
||||
() => [model.value.name, model.value.code, model.value.status] as const,
|
||||
([name, code, status]) => {
|
||||
syncingFromSource = true;
|
||||
searchModel.keyword = name ?? code ?? '';
|
||||
searchModel.status = status;
|
||||
syncingFromSource = false;
|
||||
},
|
||||
{ immediate: true, flush: 'sync' }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => [searchModel.keyword, searchModel.status] as const,
|
||||
([keywordValue, status]) => {
|
||||
if (syncingFromSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keywordText = keywordValue.trim() || undefined;
|
||||
model.value.name = keywordText;
|
||||
model.value.code = keywordText;
|
||||
model.value.status = status;
|
||||
},
|
||||
{ flush: 'sync' }
|
||||
);
|
||||
|
||||
const fields = computed<SearchField[]>(() => [
|
||||
{
|
||||
key: 'keyword',
|
||||
label: $t('page.system.role.searchKeyword'),
|
||||
type: 'input',
|
||||
placeholder: $t('page.system.role.searchPlaceholder')
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: $t('page.system.role.roleStatus'),
|
||||
type: 'select',
|
||||
placeholder: $t('page.system.role.form.roleStatus'),
|
||||
options: commonStatusOptions.map(item => ({
|
||||
label: $t(item.label),
|
||||
value: item.value
|
||||
}))
|
||||
}
|
||||
]);
|
||||
|
||||
function reset() {
|
||||
emit('reset');
|
||||
}
|
||||
@@ -36,20 +80,7 @@ function search() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel :model="model" :action-col-lg="8" @reset="reset" @search="search">
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.role.searchKeyword')" prop="name">
|
||||
<ElInput v-model="keyword" clearable :placeholder="$t('page.system.role.searchPlaceholder')" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.role.roleStatus')" prop="status">
|
||||
<ElSelect v-model="model.status" clearable :placeholder="$t('page.system.role.form.roleStatus')">
|
||||
<ElOption v-for="{ label, value } in commonStatusOptions" :key="value" :label="$t(label)" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
<TableSearchFields v-model="searchModel" :fields="fields" :columns="3" @reset="reset" @search="search" />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -134,7 +134,7 @@ async function loadTreeData() {
|
||||
|
||||
if (!error) {
|
||||
treeData.value = data || [];
|
||||
|
||||
|
||||
// 数据加载完成后,展开前两层节点
|
||||
await nextTick();
|
||||
expandFirstTwoLevels();
|
||||
@@ -173,7 +173,7 @@ async function loadTreeDataByQuery(query: Api.SystemManage.UserManagementRelatio
|
||||
async function reloadTreeData() {
|
||||
// 保存当前展开状态
|
||||
saveExpandedState();
|
||||
|
||||
|
||||
checkedNodeKeys.value = [];
|
||||
await loadTreeData();
|
||||
await nextTick();
|
||||
@@ -236,10 +236,10 @@ const isAddFromTreeNode = ref(false);
|
||||
*/
|
||||
function openAdd(item?: Api.SystemManage.UserManagementRelationTreeRespVO) {
|
||||
operateType.value = 'add';
|
||||
|
||||
|
||||
// 如果是从树节点点击的新增按钮,标记为来自树节点
|
||||
isAddFromTreeNode.value = Boolean(item);
|
||||
|
||||
|
||||
// 如果是从某一行的新增按钮触发,则默认上级为当前节点用户
|
||||
// 否则默认上级为当前登录用户(在对话框组件中处理)
|
||||
editingData.value = item
|
||||
@@ -364,17 +364,17 @@ function saveExpandedState() {
|
||||
async function handleSubmitted(_relationId: string) {
|
||||
closeOperateModal();
|
||||
await reloadTreeData();
|
||||
|
||||
|
||||
// 操作完成后恢复树节点的展开状态
|
||||
await restoreExpandedState();
|
||||
|
||||
|
||||
// 重置标记
|
||||
isAddFromTreeNode.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开所有子节点(递归)
|
||||
*
|
||||
*
|
||||
* @param tree 树形组件实例
|
||||
* @param nodes 节点数据数组
|
||||
*/
|
||||
@@ -389,7 +389,7 @@ function expandNodes(tree: InstanceType<typeof ElTree>, nodes: Api.SystemManage.
|
||||
if (treeNode) {
|
||||
treeNode.expand();
|
||||
}
|
||||
|
||||
|
||||
// 递归展开子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
expandNodes(tree, node.children);
|
||||
@@ -399,7 +399,7 @@ function expandNodes(tree: InstanceType<typeof ElTree>, nodes: Api.SystemManage.
|
||||
|
||||
/**
|
||||
* 展开树的前两层节点
|
||||
*
|
||||
*
|
||||
* 只展开根节点和它们的直接子节点,第三层及更深层保持折叠
|
||||
*/
|
||||
function expandFirstTwoLevels() {
|
||||
@@ -414,7 +414,7 @@ function expandFirstTwoLevels() {
|
||||
if (treeNode) {
|
||||
treeNode.expand();
|
||||
}
|
||||
|
||||
|
||||
// 展开第二层(根节点的直接子节点)
|
||||
if (rootNode.children && rootNode.children.length > 0) {
|
||||
for (const childNode of rootNode.children) {
|
||||
@@ -429,12 +429,12 @@ function expandFirstTwoLevels() {
|
||||
|
||||
/**
|
||||
* 恢复树节点的展开状态
|
||||
*
|
||||
*
|
||||
* 根据之前保存的展开状态,恢复对应的节点展开
|
||||
*/
|
||||
async function restoreExpandedState() {
|
||||
await nextTick();
|
||||
|
||||
|
||||
const tree = relationTreeRef.value;
|
||||
if (!tree || !expandedNodeKeys.value.length) {
|
||||
return;
|
||||
@@ -496,7 +496,7 @@ onMounted(async () => {
|
||||
/>
|
||||
|
||||
<!-- 树形卡片区域 -->
|
||||
<ElCard class="flex-1-hidden card-wrapper min-h-0">
|
||||
<ElCard class="min-h-0 flex-1-hidden card-wrapper">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between gap-12px">
|
||||
<div class="flex items-center gap-10px">
|
||||
|
||||
@@ -294,7 +294,7 @@ watch(visible, value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
preset="sm"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
:scrollbar="false"
|
||||
@@ -302,12 +302,12 @@ watch(visible, value => {
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="上级用户" prop="managerUserId">
|
||||
<ElSelect
|
||||
v-model="model.managerUserId"
|
||||
class="w-full"
|
||||
placeholder="请选择上级用户"
|
||||
<ElSelect
|
||||
v-model="model.managerUserId"
|
||||
class="w-full"
|
||||
placeholder="请选择上级用户"
|
||||
filterable
|
||||
:disabled="props.operateType === 'add' && props.isAddFromTreeNode"
|
||||
>
|
||||
@@ -315,7 +315,7 @@ watch(visible, value => {
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="下级用户" prop="subordinateUserId">
|
||||
<ElSelect
|
||||
v-model="model.subordinateUserId"
|
||||
@@ -330,7 +330,7 @@ watch(visible, value => {
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="生效开始时间" prop="effectiveFrom" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.effectiveFrom"
|
||||
@@ -342,7 +342,7 @@ watch(visible, value => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="生效结束时间" prop="effectiveUntil" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.effectiveUntil"
|
||||
|
||||
@@ -226,7 +226,7 @@ watch(visible, async value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="lg"
|
||||
preset="md"
|
||||
:loading="loading"
|
||||
:confirm-loading="submitting"
|
||||
max-body-height="70vh"
|
||||
|
||||
@@ -160,7 +160,7 @@ watch(visible, async value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
preset="sm"
|
||||
:confirm-loading="submitting"
|
||||
:scrollbar="false"
|
||||
@confirm="handleSubmit"
|
||||
@@ -168,12 +168,12 @@ watch(visible, async value => {
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<BusinessFormSection :title="$t('page.system.user.sections.basicInfo')">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.deptName')">
|
||||
<ElInput :model-value="dept?.name || $t('common.noData')" disabled />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.candidateUser')" prop="userId">
|
||||
<ElSelect
|
||||
v-model="model.userId"
|
||||
@@ -185,7 +185,7 @@ watch(visible, async value => {
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.effectiveFrom')" prop="effectiveFrom" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.effectiveFrom"
|
||||
@@ -197,7 +197,7 @@ watch(visible, async value => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.effectiveUntil')" prop="effectiveUntil" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.effectiveUntil"
|
||||
|
||||
@@ -194,7 +194,7 @@ watch(visible, async value => {
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
preset="sm"
|
||||
:confirm-loading="submitting"
|
||||
:scrollbar="false"
|
||||
@confirm="handleSubmit"
|
||||
@@ -219,14 +219,14 @@ watch(visible, async value => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.orgTypeLabel')" prop="orgType">
|
||||
<ElSelect v-model="model.orgType" :placeholder="$t('page.system.user.form.orgTypeLabel')">
|
||||
<ElOption v-for="item in orgTypeOptions" :key="item.value" :label="$t(item.label)" :value="item.value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.orgCode')" prop="code">
|
||||
<ElSelect v-if="isCodeSelectable" v-model="model.code" clearable filterable placeholder="请选择组织编码">
|
||||
<ElOption
|
||||
@@ -239,7 +239,7 @@ watch(visible, async value => {
|
||||
<ElInput v-else v-model="model.code" :placeholder="$t('page.system.user.form.orgCode')" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.orgSort')" prop="sort">
|
||||
<ElInputNumber
|
||||
v-model="model.sort"
|
||||
@@ -249,7 +249,7 @@ watch(visible, async value => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.userStatus')" prop="status">
|
||||
<ElRadioGroup v-model="model.status" class="business-form-radio-group">
|
||||
<ElRadio v-for="item in commonStatusOptions" :key="item.value" :value="item.value">
|
||||
|
||||
@@ -118,16 +118,17 @@ watch(visible, async value => {
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" label-position="top">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.userName')">
|
||||
<ElInput :model-value="displayUsername" disabled />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem :label="$t('page.system.user.resignedAt')">
|
||||
<ElCol :span="24">
|
||||
<ElFormItem :label="$t('page.system.user.resignedAt')" style="width: 100%">
|
||||
<ElDatePicker
|
||||
v-model="model.resignedAt"
|
||||
class="w-full"
|
||||
style="width: 100%"
|
||||
type="datetime"
|
||||
clearable
|
||||
:placeholder="$t('page.system.user.form.resignedAt')"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { SYSTEM_USER_COMPANY_DICT_CODE } from '@/constants/dict';
|
||||
import { computed } from 'vue';
|
||||
import { commonStatusOptions } from '@/constants/business';
|
||||
import { translateOptions } from '@/utils/common';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
import TableSearchFields from '@/components/custom/table-search-fields.vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'UserSearch' });
|
||||
@@ -13,7 +11,7 @@ interface Props {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
disabled: false
|
||||
});
|
||||
|
||||
@@ -22,81 +20,61 @@ interface Emits {
|
||||
(e: 'search'): void;
|
||||
}
|
||||
|
||||
defineEmits<Emits>();
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<Api.SystemManage.UserSearchParams>('model', { required: true });
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const fields = computed<any[]>(() => [
|
||||
{
|
||||
key: 'nickname',
|
||||
label: $t('page.system.user.nickName'),
|
||||
type: 'input',
|
||||
placeholder: $t('page.system.user.form.nickName')
|
||||
},
|
||||
{
|
||||
key: 'mobile',
|
||||
label: $t('page.system.user.userPhone'),
|
||||
type: 'input',
|
||||
placeholder: $t('page.system.user.form.userPhone')
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: $t('page.system.user.userStatus'),
|
||||
type: 'select',
|
||||
placeholder: $t('page.system.user.form.userStatus'),
|
||||
options: commonStatusOptions.map(o => ({
|
||||
label: $t(o.label as App.I18n.I18nKey),
|
||||
value: o.value
|
||||
}))
|
||||
},
|
||||
{
|
||||
key: 'company',
|
||||
label: '所属公司',
|
||||
type: 'dict',
|
||||
dictCode: 'system_user_company',
|
||||
placeholder: '请选择所属公司'
|
||||
},
|
||||
{
|
||||
key: 'roleId',
|
||||
label: $t('page.system.user.userRole'),
|
||||
type: 'select',
|
||||
placeholder: $t('page.system.user.form.userRole'),
|
||||
options: props.roleOptions.map(r => ({
|
||||
label: r.name,
|
||||
value: r.id
|
||||
}))
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel
|
||||
:model="model"
|
||||
<TableSearchFields
|
||||
v-model="model"
|
||||
:fields="fields"
|
||||
:columns="3"
|
||||
:disabled="disabled"
|
||||
:action-col-lg="24"
|
||||
:action-col-md="24"
|
||||
:action-col-sm="24"
|
||||
@reset="$emit('reset')"
|
||||
@search="$emit('search')"
|
||||
>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.user.nickName')" prop="nickname">
|
||||
<ElInput
|
||||
v-model="model.nickname"
|
||||
clearable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.user.form.nickName')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.user.userPhone')" prop="mobile">
|
||||
<ElInput
|
||||
v-model="model.mobile"
|
||||
clearable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.user.form.userPhone')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.user.userStatus')" prop="status">
|
||||
<ElSelect
|
||||
v-model="model.status"
|
||||
clearable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.user.form.userStatus')"
|
||||
>
|
||||
<ElOption
|
||||
v-for="{ label, value } in translateOptions(commonStatusOptions)"
|
||||
:key="value"
|
||||
:label="label"
|
||||
:value="value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem label="所属公司" prop="company">
|
||||
<DictSelect
|
||||
v-model="model.company"
|
||||
:dict-code="SYSTEM_USER_COMPANY_DICT_CODE"
|
||||
filterable
|
||||
:disabled="disabled"
|
||||
placeholder="请选择所属公司"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="6" :md="8" :sm="12">
|
||||
<ElFormItem :label="$t('page.system.user.userRole')" prop="roleId">
|
||||
<ElSelect
|
||||
v-model="model.roleId"
|
||||
clearable
|
||||
filterable
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('page.system.user.form.userRole')"
|
||||
>
|
||||
<ElOption v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
@search="emit('search')"
|
||||
@reset="emit('reset')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user