|
@@ -1,9 +1,363 @@
|
|
|
-<template>用户管理</template>
|
|
|
+<template>
|
|
|
+ <CzrContent
|
|
|
+ v-model:tableHead="state.query.head"
|
|
|
+ @handleReset="onReset"
|
|
|
+ @handleSearch="onSearch"
|
|
|
+ >
|
|
|
+ <template #tableTitle>
|
|
|
+ <div class="flex gap-2.5"></div>
|
|
|
+ </template>
|
|
|
+ <template #buttons>
|
|
|
+ <div class="flex items-center gap-2.5">
|
|
|
+ <CzrForm class="bm-filter" label-width="0px" @handleEnter="onSearch">
|
|
|
+ <CzrFormColumn
|
|
|
+ width="6.68rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.query.form.tenantId"
|
|
|
+ link="select"
|
|
|
+ :options="DictionaryStore.tenants.list"
|
|
|
+ placeholder="全部租戶"
|
|
|
+ />
|
|
|
+ <CzrFormColumn
|
|
|
+ width="19rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.query.form.loginTime"
|
|
|
+ link="date"
|
|
|
+ type="daterange"
|
|
|
+ placeholder="最后登录时间"
|
|
|
+ />
|
|
|
+ <CzrFormColumn
|
|
|
+ width="19rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.query.form.createTime"
|
|
|
+ link="date"
|
|
|
+ type="daterange"
|
|
|
+ placeholder="注册时间"
|
|
|
+ />
|
|
|
+ <CzrFormColumn
|
|
|
+ width="6.68rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.query.form.enabled"
|
|
|
+ link="select"
|
|
|
+ :options="DictionaryStore.trueFalseStatus"
|
|
|
+ placeholder="状态"
|
|
|
+ />
|
|
|
+ <CzrFormColumn
|
|
|
+ width="6.68rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.query.form.xxx"
|
|
|
+ link="select"
|
|
|
+ :options="[]"
|
|
|
+ placeholder="全部角色"
|
|
|
+ />
|
|
|
+ <CzrFormColumn
|
|
|
+ width="15.63rem"
|
|
|
+ class="__czr-table-form-column"
|
|
|
+ :span="24"
|
|
|
+ label-width="0px"
|
|
|
+ v-model:param="state.text"
|
|
|
+ placeholder="输入关键词以检索"
|
|
|
+ :prefix-icon="Search"
|
|
|
+ />
|
|
|
+ <CzrButton type="add" @click="onInvite" title="新增用户" />
|
|
|
+ <CzrButton type="add" @click="onAdd" title="新增账号" />
|
|
|
+ </CzrForm>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #table>
|
|
|
+ <CzrTable
|
|
|
+ v-loading="state.query.loading"
|
|
|
+ v-model:data="state.query.result.data"
|
|
|
+ :head="state.query.head"
|
|
|
+ :total="state.query.result.total"
|
|
|
+ :page="state.query.page.pageNum"
|
|
|
+ :pageSize="state.query.page.pageSize"
|
|
|
+ @handlePage="onPage"
|
|
|
+ @handleSort="onSort"
|
|
|
+ v-model:selected="state.query.selected"
|
|
|
+ >
|
|
|
+ <template #caozuo-column-value="{ scope }">
|
|
|
+ <div class="__czr-table-operations">
|
|
|
+ <CzrButton type="table" title="编辑" @click="onEdit(scope.row)" />
|
|
|
+ <CzrButton type="table-del" @click="onDel(scope.row)" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </CzrTable>
|
|
|
+ </template>
|
|
|
+ </CzrContent>
|
|
|
+ <detailCom
|
|
|
+ v-model:show="state.detail.show"
|
|
|
+ :transfer="state.detail.transfer"
|
|
|
+ @refresh="onSearch"
|
|
|
+ />
|
|
|
+ <CzrDialog
|
|
|
+ :show="state.invite.show"
|
|
|
+ title="新增用户"
|
|
|
+ @onClose="state.invite.show = false"
|
|
|
+ width="40rem"
|
|
|
+ :show-submit="false"
|
|
|
+ :show-close="false"
|
|
|
+ >
|
|
|
+ <div class="bm-form">
|
|
|
+ <CzrFormColumn
|
|
|
+ :span="24"
|
|
|
+ label="角色"
|
|
|
+ v-model:param="state.invite.roles"
|
|
|
+ link="select"
|
|
|
+ :options="[]"
|
|
|
+ :multiple="true"
|
|
|
+ />
|
|
|
+ <div class="__czr-title_1 mb-2">
|
|
|
+ 邀请链接
|
|
|
+ <div class="ml-2 text-xs font-normal text-[var(--czr-error-color)]">
|
|
|
+ 链接24小时内有效
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <CzrFormColumn
|
|
|
+ :span="24"
|
|
|
+ label="邀请链接"
|
|
|
+ v-model:param="state.invite.url"
|
|
|
+ :readonly="true"
|
|
|
+ >
|
|
|
+ <template #suffix>
|
|
|
+ <CopyDocument
|
|
|
+ class="w-4 cursor-pointer"
|
|
|
+ @click="onCopy(state.invite.url)"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </CzrFormColumn>
|
|
|
+ </div>
|
|
|
+ </CzrDialog>
|
|
|
+</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { reactive } from 'vue'
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ getCurrentInstance,
|
|
|
+ onMounted,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ watch,
|
|
|
+} from 'vue'
|
|
|
+import { CopyDocument, Search } from '@element-plus/icons-vue'
|
|
|
+import { debounce } from 'lodash'
|
|
|
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import detailCom from './detail.vue'
|
|
|
+import { userPage } from '@/api/modules/center/user'
|
|
|
+import { copy } from '@/utils/czr-util'
|
|
|
|
|
|
-const state: any = reactive({})
|
|
|
+const AppStore = useAppStore()
|
|
|
+const DialogStore = useDialogStore()
|
|
|
+const DictionaryStore = useDictionaryStore()
|
|
|
+const emit = defineEmits([])
|
|
|
+const props = defineProps({})
|
|
|
+const { proxy }: any = getCurrentInstance()
|
|
|
+const state: any = reactive({
|
|
|
+ text: '',
|
|
|
+ query: {
|
|
|
+ init: false,
|
|
|
+ loading: false,
|
|
|
+ head: [
|
|
|
+ { value: 'loginId', label: '账号', show: true },
|
|
|
+ { value: 'name', label: '用户名', show: true },
|
|
|
+ {
|
|
|
+ value: 'createTime',
|
|
|
+ label: '注册时间',
|
|
|
+ show: true,
|
|
|
+ width: 180,
|
|
|
+ datetime: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'loginTime',
|
|
|
+ label: '最后登录时间',
|
|
|
+ show: true,
|
|
|
+ width: 180,
|
|
|
+ datetime: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'enabled',
|
|
|
+ label: '状态',
|
|
|
+ show: true,
|
|
|
+ dictList: computed(() => DictionaryStore.trueFalseStatus),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: 'caozuo',
|
|
|
+ label: '操作',
|
|
|
+ show: true,
|
|
|
+ width: 200,
|
|
|
+ fixed: 'right',
|
|
|
+ popover: false,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ page: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 20,
|
|
|
+ },
|
|
|
+ form: {},
|
|
|
+ formReal: {},
|
|
|
+ sort: {},
|
|
|
+ result: {
|
|
|
+ total: 0,
|
|
|
+ data: [],
|
|
|
+ },
|
|
|
+ selected: [],
|
|
|
+ },
|
|
|
+ detail: {
|
|
|
+ show: false,
|
|
|
+ transfer: {},
|
|
|
+ },
|
|
|
+ invite: {
|
|
|
+ show: false,
|
|
|
+ url: '',
|
|
|
+ roles: [],
|
|
|
+ },
|
|
|
+})
|
|
|
+const setText = debounce((v) => {
|
|
|
+ state.query.form.name = v
|
|
|
+}, 1000)
|
|
|
+watch(
|
|
|
+ () => state.text,
|
|
|
+ (n) => {
|
|
|
+ setText(n)
|
|
|
+ },
|
|
|
+)
|
|
|
+watch(
|
|
|
+ () => state.query.form,
|
|
|
+ (n) => {
|
|
|
+ if (state.query.init) {
|
|
|
+ onSearch()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true },
|
|
|
+)
|
|
|
+const onSort = ({ key, value }) => {
|
|
|
+ state.query.sort[key] = value
|
|
|
+ onSearch()
|
|
|
+}
|
|
|
+const onPage = (pageNum, pageSize) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ state.query.init = true
|
|
|
+ }, 100)
|
|
|
+ state.query.page = {
|
|
|
+ pageNum: pageNum,
|
|
|
+ pageSize: pageSize,
|
|
|
+ }
|
|
|
+ const params = {
|
|
|
+ page: state.query.page.pageNum,
|
|
|
+ size: state.query.page.pageSize,
|
|
|
+ }
|
|
|
+ // 添加表单参数
|
|
|
+ for (const [k, v] of Object.entries(state.query.formReal)) {
|
|
|
+ if (proxy.$czrUtil.isValue(v)) {
|
|
|
+ if (k === 'loginTime') {
|
|
|
+ params['loginTimeStart'] = v[0]
|
|
|
+ params['loginTimeEnd'] = v[1]
|
|
|
+ } else if (k === 'createTime') {
|
|
|
+ params['createTimeStart'] = v[0]
|
|
|
+ params['createTimeEnd'] = v[1]
|
|
|
+ } else {
|
|
|
+ params[k] = v
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加排序参数
|
|
|
+ for (const [k, v] of Object.entries(state.query.sort)) {
|
|
|
+ }
|
|
|
+ state.query.loading = true
|
|
|
+ userPage(params)
|
|
|
+ .then(({ data }: any) => {
|
|
|
+ state.query.result.total = data.totalElements
|
|
|
+ state.query.result.data = data.content
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ .finally(() => {
|
|
|
+ state.query.loading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+const onSearch = () => {
|
|
|
+ state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
|
|
|
+ onPage(1, state.query.page.pageSize)
|
|
|
+}
|
|
|
+const onReset = () => {
|
|
|
+ state.query.page = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 20,
|
|
|
+ }
|
|
|
+ state.query.form = {}
|
|
|
+ state.query.sort = {}
|
|
|
+ onSearch()
|
|
|
+}
|
|
|
+const onAdd = () => {
|
|
|
+ state.detail.transfer = {
|
|
|
+ mode: 'add',
|
|
|
+ }
|
|
|
+ state.detail.show = true
|
|
|
+}
|
|
|
+const onEdit = (row) => {
|
|
|
+ state.detail.transfer = {
|
|
|
+ mode: 'edit',
|
|
|
+ id: row.id,
|
|
|
+ }
|
|
|
+ state.detail.show = true
|
|
|
+}
|
|
|
+const onDel = (row: any) => {
|
|
|
+ DialogStore.confirm({
|
|
|
+ title: '删除确认',
|
|
|
+ content: `请确认是否删除`,
|
|
|
+ onSubmit: () => {
|
|
|
+ // appDel(row.id)
|
|
|
+ // .then(() => {
|
|
|
+ // ElMessage.success('删除成功!')
|
|
|
+ // })
|
|
|
+ // .catch(() => {})
|
|
|
+ // .finally(() => {
|
|
|
+ // onSearch()
|
|
|
+ // })
|
|
|
+ },
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const onInvite = () => {
|
|
|
+ state.invite.url = 'https://cn.element-plus.org/zh-CN/component/input.html'
|
|
|
+ state.invite.roles = []
|
|
|
+ state.invite.show = true
|
|
|
+}
|
|
|
+const onCopy = (str) => {
|
|
|
+ copy(str)
|
|
|
+ ElMessage.success('复制成功!')
|
|
|
+}
|
|
|
+onMounted(() => {
|
|
|
+ initDictionary()
|
|
|
+ onReset()
|
|
|
+})
|
|
|
+const initDictionary = () => {
|
|
|
+ DictionaryStore.initTenants()
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.model {
|
|
|
+ width: 100%;
|
|
|
+ background-image: url('@/assets/images/model/model-icon-7.png');
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ padding: 1rem;
|
|
|
+ border-radius: 10px;
|
|
|
+ box-shadow: 0rem 0.25rem 0.63rem 0rem rgba(40, 83, 247, 0.05);
|
|
|
+ border: var(--czr-border);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+</style>
|