Merge remote-tracking branch 'origin/leng_dev' into lei_dev

# Conflicts:
#	src/views/admin/tenant/form.vue
This commit is contained in:
aeizzz 2023-03-02 13:23:13 +08:00
commit 34b00cf7e2
15 changed files with 354 additions and 358 deletions

View File

@ -65,7 +65,7 @@
"not dead"
],
"bugs": {
"url": "https://gitee.com/lyt-top/vue-next-admin/issues"
"url": "https://pig4cloud.com"
},
"engines": {
"node": ">=16.0.0",

View File

@ -63,7 +63,7 @@ export function editInfo(obj: Object) {
})
}
export function password(obj: Object){
export function password(obj: Object) {
return request({
url: '/admin/user/password',
method: 'put',

View File

@ -1,6 +1,6 @@
import request from '/@/utils/request';
import { Session } from "/@/utils/storage";
import { rule } from "/@/utils/validate"
import { validateNull } from "/@/utils/validate"
import { useUserInfo } from "/@/stores/userInfo";
/**
@ -99,7 +99,7 @@ export const checkToken = (refreshTime: number, refreshLock: boolean) => {
params: { token: Session.get("token") }
})
.then((response) => {
if (rule.validatenull(response) || response.code === 1) {
if (validateNull(response) || response.code === 1) {
clearInterval(refreshTime)
return
}

View File

@ -1,20 +1,28 @@
<template>
<div class="layout-footer pb15">
<div class="layout-footer-warp">
<div>vue-next-adminMade by lyt with </div>
<div class="mt5">深圳市 xxx 公司版权所有</div>
<div class="mt5">{{ footerAuthor }}</div>
</div>
</div>
</template>
<script setup lang="ts" name="layoutFooter">
//
import { useThemeConfig } from '/@/stores/themeConfig';
//
const storesThemeConfig = useThemeConfig()
const { themeConfig } = storeToRefs(storesThemeConfig)
//
const footerAuthor = computed(() => {
return themeConfig.value.footerAuthor;
});
</script>
<style scoped lang="scss">
.layout-footer {
width: 100%;
display: flex;
&-warp {
margin: auto;
color: var(--el-text-color-secondary);

View File

@ -1,4 +1,4 @@
import {defineStore} from 'pinia';
import { defineStore } from 'pinia';
/**
*
@ -132,16 +132,18 @@ export const useThemeConfig = defineStore('themeConfig', {
/**
* /
*/
// 网站主标题(菜单导航、浏览器当前网页标题)
globalTitle: 'PigX 快速开发框架',
// 网站主标题菜单导航、浏览器当前网页标题、登录form顶部右侧
globalTitle: 'PigX 快速开发框架1',
// 网站副标题(登录左侧底部页顶部文字)
globalViceTitle: 'PigX 快速开发框架2',
// 网站副标题(登录页顶部文字)
globalViceTitle: 'PigX 快速开发框架',
// 网站副标题(登录页顶部文字)
globalViceTitleMsg: '专注、免费、开源、维护、解疑',
globalViceTitleMsg: '专注、免费、开源、维护、解疑3',
// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn
globalI18n: 'zh-cn',
// 默认全局组件大小,可选值"<large|'default'|small>",默认 'large'
globalComponentSize: 'large'
globalComponentSize: 'large',
// footer 页面作者
footerAuthor: '©2023 pig4cloud.com'
},
}),

View File

@ -88,5 +88,6 @@ declare interface ThemeConfigState {
globalViceTitleMsg: string;
globalI18n: string;
globalComponentSize: string;
footerAuthor: string;
};
}

View File

@ -1,42 +1,42 @@
import axios, {AxiosInstance, InternalAxiosRequestConfig} from 'axios';
import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
import errorCode from './errorCode'
import {ElMessage, ElMessageBox} from 'element-plus';
import {Session, Local} from '/@/utils/storage';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Session, Local } from '/@/utils/storage';
import qs from 'qs';
// 配置新建一个 axios 实例
const service: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 50000,
headers: {'Content-Type': 'application/json'},
headers: { 'Content-Type': 'application/json' },
paramsSerializer: {
serialize(params) {
return qs.stringify(params, {allowDots: true});
return qs.stringify(params, { allowDots: true });
},
},
});
// 添加请求拦截器
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// get查询参数序列化
if (config.method === 'get') {
config.paramsSerializer = (params: any) => {
return qs.stringify(params, {arrayFormat: 'repeat'})
}
}
// 统一增加 token
const isToken = (config.headers || {}).isToken === false
if (Session.get('token') && !isToken) {
config.headers!['Authorization'] = `Bearer ${Session.get('token')}`;
// get查询参数序列化
if (config.method === 'get') {
config.paramsSerializer = (params: any) => {
return qs.stringify(params, { arrayFormat: 'repeat' })
}
}
// 统一增加 token
const isToken = (config.headers || {}).isToken === false
if (Session.get('token') && !isToken) {
config.headers!['Authorization'] = `Bearer ${Session.get('token')}`;
}
// 统一增加租户信息
if (Local.get('tenantId')) {
config.headers!['TENANT-ID'] = Local.get('tenantId');
}
// 统一增加租户信息
if (Local.get('tenantId')) {
config.headers!['TENANT-ID'] = Local.get('tenantId');
}
return config;
},
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
@ -63,15 +63,9 @@ service.interceptors.response.use((res: any) => {
window.location.href = '/'; // 去登录页
return
})
.catch(() => {
})
}
if (status !== 200 || error.response.data.code === 1) {
ElMessage.error(message)
return Promise.reject(new Error(message))
}
return Promise.reject(error);
return Promise.reject(error.response.data);
})

View File

@ -1,49 +1,8 @@
/**
* @desc []
* @example
* import { validateRule } from "@/utils/validateRules";
* rules: [
* { validator: validateRule.emailValue, trigger: 'blur'}
* ]
*/
export const getRegExp = function (validatorName) {
const commonRegExp = {
number: '/^[-]?\\d+(\\.\\d+)?$/',
letter: '/^[A-Za-z]+$/',
letterAndNumber: '/^[A-Za-z0-9]+$/',
mobilePhone: '/^[1][3-9][0-9]{9}$/',
letterStartNumberIncluded: '/^[A-Za-z]+[A-Za-z\\d]*$/',
noChinese: '/^[^\u4e00-\u9fa5]+$/',
chinese: '/^[\u4e00-\u9fa5]+$/',
email: '/^([-_A-Za-z0-9.]+)@([_A-Za-z0-9]+\\.)+[A-Za-z0-9]{2,3}$/',
url: '/^([hH][tT]{2}[pP]:\\/\\/|[hH][tT]{2}[pP][sS]:\\/\\/)(([A-Za-z0-9-~]+)\\.)+([A-Za-z0-9-~\\/])+$/',
}
return commonRegExp[validatorName]
}
const validateFn = function (validatorName, rule, value, callback, defaultErrorMsg) {
//空值不校验
if (validatenull(value) || (value.length <= 0)) {
callback()
return
}
const reg = eval(getRegExp(validatorName))
if (!reg.test(value)) {
let errTxt = rule.errorMsg || defaultErrorMsg
callback(new Error(errTxt))
} else {
callback()
}
}
/**
*
* @param val
*/
const validatenull = (val: any) => {
export const validateNull = (val: any) => {
if (typeof val === 'boolean') {
return false
}
@ -62,6 +21,7 @@ const validatenull = (val: any) => {
}
export const rule = {
/**
* 线
@ -106,6 +66,11 @@ export const rule = {
*/
validatePhone(rule: any, value: any, callback: any) {
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/
if (value.indexOf('****') >= 0) {
return callback()
}
if (!isPhone.test(value)) {
callback(new Error('请输入合法手机号'))
} else {
@ -113,65 +78,60 @@ export const rule = {
}
},
/* 数字 */
number(rule, value, callback) {
validateFn('number', rule, value, callback, '[' + rule.label + ']包含非数字字符')
validateFn('number', rule, value, callback, '包含非数字字符')
},
/* 字母 */
letter(rule, value, callback) {
validateFn('letter', rule, value, callback, '[' + rule.label + ']包含非字母字符')
validateFn('letter', rule, value, callback, '包含非字母字符')
},
/* 字母和数字 */
letterAndNumber(rule, value, callback) {
validateFn('letterAndNumber', rule, value, callback, '[' + rule.label + ']只能输入字母或数字')
validateFn('letterAndNumber', rule, value, callback, '只能输入字母或数字')
},
/* 手机号码 */
mobilePhone(rule, value, callback) {
validateFn('mobilePhone', rule, value, callback, '[' + rule.label + ']手机号码格式有误')
validateFn('mobilePhone', rule, value, callback, '手机号码格式有误')
},
/* 字母开头,仅可包含数字 */
letterStartNumberIncluded(rule, value, callback) {
validateFn('letterStartNumberIncluded', rule, value, callback, '[' + rule.label + ']必须以字母开头,可包含数字')
validateFn('letterStartNumberIncluded', rule, value, callback, '必须以字母开头,可包含数字')
},
/* 禁止中文输入 */
noChinese(rule, value, callback) {
validateFn('noChinese', rule, value, callback, '[' + rule.label + ']不可输入中文字符')
validateFn('noChinese', rule, value, callback, '不可输入中文字符')
},
/* 必须中文输入 */
chinese(rule, value, callback) {
validateFn('chinese', rule, value, callback, '[' + rule.label + ']只能输入中文字符')
validateFn('chinese', rule, value, callback, '只能输入中文字符')
},
/* 电子邮箱 */
email(rule, value, callback) {
validateFn('email', rule, value, callback, '[' + rule.label + ']邮箱格式有误')
validateFn('email', rule, value, callback, '邮箱格式有误')
},
/* URL网址 */
url(rule, value, callback) {
validateFn('url', rule, value, callback, '[' + rule.label + ']URL格式有误')
validateFn('url', rule, value, callback, 'URL格式有误')
},
regExp(rule, value, callback) {
//空值不校验
if (validatenull(value) || (value.length <= 0)) {
if (validateNull(value) || (value.length <= 0)) {
callback()
return
}
const pattern = eval(rule.regExp)
if (!pattern.test(value)) {
let errTxt = rule.errorMsg || '[' + rule.label + ']invalid value'
let errTxt = rule.errorMsg || 'invalid value'
callback(new Error(errTxt))
} else {
callback()
@ -180,4 +140,46 @@ export const rule = {
}
/**
* @desc []
* @example
* import { validateRule } from "@/utils/validateRules";
* rules: [
* { validator: validateRule.emailValue, trigger: 'blur'}
* ]
*/
export const getRegExp = function (validatorName) {
const commonRegExp = {
number: '/^[-]?\\d+(\\.\\d+)?$/',
letter: '/^[A-Za-z]+$/',
letterAndNumber: '/^[A-Za-z0-9]+$/',
mobilePhone: '/^[1][3-9][0-9]{9}$/',
letterStartNumberIncluded: '/^[A-Za-z]+[A-Za-z\\d]*$/',
noChinese: '/^[^\u4e00-\u9fa5]+$/',
chinese: '/^[\u4e00-\u9fa5]+$/',
email: '/^([-_A-Za-z0-9.]+)@([_A-Za-z0-9]+\\.)+[A-Za-z0-9]{2,3}$/',
url: '/^([hH][tT]{2}[pP]:\\/\\/|[hH][tT]{2}[pP][sS]:\\/\\/)(([A-Za-z0-9-~]+)\\.)+([A-Za-z0-9-~\\/])+$/',
}
return commonRegExp[validatorName]
}
const validateFn = function (validatorName, rule, value, callback, defaultErrorMsg) {
//空值不校验
if (validateNull(value) || (value.length <= 0)) {
callback()
return
}
const reg = eval(getRegExp(validatorName))
if (!reg.test(value)) {
let errTxt = rule.errorMsg || defaultErrorMsg
callback(new Error(errTxt))
} else {
callback()
}
}

View File

@ -5,15 +5,15 @@
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item :label="$t('audit.auditName')" prop="auditName">
<el-input :placeholder="t('audit.inputAuditNameTip')" v-model="state.queryForm.auditName"
style="max-width: 180px"/>
style="max-width: 180px" />
</el-form-item>
<el-form-item :label="$t('audit.auditField')" prop="auditField">
<el-input :placeholder="t('audit.inputAuditFieldTip')" v-model="state.queryForm.auditField"
style="max-width: 180px"/>
style="max-width: 180px" />
</el-form-item>
<el-form-item :label="$t('audit.createBy')" prop="createBy">
<el-input :placeholder="t('audit.inputCreateByTip')" v-model="state.queryForm.createBy"
style="max-width: 180px"/>
style="max-width: 180px" />
</el-form-item>
<el-form-item class="ml2">
<el-button formDialogRef icon="search" type="primary" @click="getDataList">
@ -26,52 +26,48 @@
<el-row>
<div class="mb8" style="width: 100%">
<el-button formDialogRef icon="Download" type="primary" class="ml10" @click="exportExcel"
v-auth="'sys_audit_export'">
v-auth="'sys_audit_export'">
{{ $t('common.exportBtn') }}
</el-button>
<el-button formDialogRef :disabled="multiple" icon="Delete" type="primary" class="ml10"
v-auth="'sys_audit_del'" @click="handleDelete(selectObjs)">
<el-button formDialogRef :disabled="multiple" icon="Delete" type="primary" class="ml10" v-auth="'sys_audit_del'"
@click="handleDelete(selectObjs)">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
@selection-change="handleSelectionChange" @sort-change="sortChangeHandle">
<el-table-column type="selection" width="60" align="center"/>
<el-table-column type="index" :label="t('audit.index')" width="80"/>
<el-table-column prop="auditName" :label="t('audit.auditName')" show-overflow-tooltip/>
<el-table-column prop="auditField" :label="t('audit.auditField')" show-overflow-tooltip/>
<el-table-column prop="beforeVal" :label="t('audit.beforeVal')" show-overflow-tooltip/>
<el-table-column prop="afterVal" :label="t('audit.afterVal')" show-overflow-tooltip/>
<el-table-column prop="createBy" :label="t('audit.createBy')" show-overflow-tooltip/>
<el-table-column prop="createTime" :label="t('audit.createTime')" show-overflow-tooltip/>
@selection-change="handleSelectionChange" @sort-change="sortChangeHandle">
<el-table-column type="selection" width="60" align="center" />
<el-table-column type="index" :label="t('audit.index')" width="80" />
<el-table-column prop="auditName" :label="t('audit.auditName')" show-overflow-tooltip />
<el-table-column prop="auditField" :label="t('audit.auditField')" show-overflow-tooltip />
<el-table-column prop="beforeVal" :label="t('audit.beforeVal')" show-overflow-tooltip />
<el-table-column prop="afterVal" :label="t('audit.afterVal')" show-overflow-tooltip />
<el-table-column prop="createBy" :label="t('audit.createBy')" show-overflow-tooltip />
<el-table-column prop="createTime" :label="t('audit.createTime')" show-overflow-tooltip />
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-button text type="primary" v-auth="'sys_audit_del'" @click="handleDelete([scope.row.id])">{{
$t('common.delBtn')
}}
$t('common.delBtn')
}}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination"/>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
</el-card>
</div>
</template>
<script setup lang="ts" name="systemSysAuditLog">
import {BasicTableProps, useTable} from "/@/hooks/table";
import {fetchList, delObjs} from "/@/api/admin/audit";
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/admin/audit";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useI18n } from "vue-i18n";
const {t} = useI18n()
//
//
const formDialogRef = ref()
const { t } = useI18n()
//
const queryRef = ref()
const showSearch = ref(true)
@ -81,7 +77,8 @@ const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
pageList: fetchList,
descs: ['create_time']
})
// table hook
@ -118,13 +115,13 @@ const handleSelectionChange = (objs: any) => {
//
const handleDelete = (ids: string[]) => {
useMessageBox().confirm(t('common.delConfirmText'))
.then(() => {
delObjs(ids).then(() => {
getDataList(false);
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
.then(() => {
delObjs(ids).then(() => {
getDataList(false);
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
})
};
</script>

View File

@ -21,7 +21,7 @@
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('sysmenu.name')" prop="name">
<el-input v-model="state.ruleForm.name" clearable placeholder="格式router.xxx"></el-input>
<el-input v-model="state.ruleForm.name" clearable :placeholder="$t('sysmenu.inputNameTip')"></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="state.ruleForm.menuType === '0'">
@ -105,7 +105,7 @@ const state = reactive({
sortOrder: 0,
menuType: '0',
keepAlive: '0',
visible: '0',
visible: '1',
embedded: '0',
},
parentData: [] as any[], //
@ -131,7 +131,7 @@ const getMenuData = () => {
sortOrder: 0,
updateBy: "",
updateTime: "",
visible: "",
visible: "1",
id: '-1', name: '根菜单', children: []
};
menu.children = res.data;

View File

@ -1,7 +1,7 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px">
<el-dialog :title="form.id ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible" :close-on-click-modal="false"
draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px">
<el-row :gutter="20">
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.name')" prop="name">
@ -25,6 +25,18 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.startTime')" prop="startTime">
<el-date-picker v-model="form.startTime" type="date" :placeholder="t('tenant.inputstartTimeTip')"
:value-format="dateTimeStr" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.endTime')" prop="endTime">
<el-date-picker v-model="form.endTime" type="date" :placeholder="t('tenant.inputendTimeTip')"
:value-format="dateTimeStr" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.status')" prop="status">
@ -34,23 +46,12 @@
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.startTime')" prop="startTime">
<el-date-picker v-model="form.startTime" type="date" :placeholder="t('tenant.inputstartTimeTip')" :value-format="dateTimeStr" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('tenant.endTime')" prop="endTime">
<el-date-picker v-model="form.endTime" type="date" :placeholder="t('tenant.inputendTimeTip')" :value-format="dateTimeStr"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false" >取消</el-button>
<el-button type="primary" @click="onSubmit" >{{ $t('common.confirmButtonText') }}</el-button>
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>

View File

@ -6,7 +6,7 @@
<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
<el-form-item :label="$t('systoken.username')" prop="username">
<el-input :placeholder="$t('systoken.inputUsernameTip')"
v-model="state.queryForm.username"></el-input>
v-model="state.queryForm.username"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList" icon="Search" type="primary">{{ $t('common.queryBtn') }}
@ -17,35 +17,34 @@
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-button :disabled="multiple" @click="handleDelete(selectObjs)" class="ml10" icon="Delete" type="primary"
v-auth="'sys_user_del'">
<el-button :disabled="multiple" @click="handleDelete(selectObjs)" class="ml10" icon="Delete"
type="primary" v-auth="'sys_user_del'">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar @queryTable="getDataList" class="ml10" style="float: right;margin-right: 20px"
v-model:showSearch="showSearch"></right-toolbar>
v-model:showSearch="showSearch"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" @selection-change="handleSelectionChange" @sort-change="sortChangeHandle"
style="width: 100%" v-loading="state.loading">
<el-table-column align="center" type="selection" width="50"/>
<el-table-column :label="$t('systoken.index')" type="index" width="80"/>
style="width: 100%" v-loading="state.loading">
<el-table-column align="center" type="selection" width="50" />
<el-table-column :label="$t('systoken.index')" type="index" width="80" />
<el-table-column :label="$t('systoken.username')" prop="username" show-overflow-tooltip
width="150"></el-table-column>
width="150"></el-table-column>
<el-table-column :label="$t('systoken.clientId')" prop="clientId" show-overflow-tooltip
width="100"></el-table-column>
width="100"></el-table-column>
<el-table-column :label="$t('systoken.accessToken')" prop="accessToken" show-overflow-tooltip>
<template #default="scope">
<el-button link type="success" v-if="Session.get('token') === scope.row.accessToken">
<el-button link type="success" v-if="filterOwnToken(scope.row)">
{{ scope.row.accessToken }}
</el-button>
</template>
</el-table-column>
<el-table-column :label="$t('systoken.expiresAt')" prop="expiresAt"
show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('systoken.expiresAt')" prop="expiresAt" show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('common.action')" width="100">
<template #default="scope">
<el-button @click="handleDelete([scope.row.accessToken])" size="small" text type="primary"
v-auth="'sys_user_del'">
v-auth="'sys_user_del'">
{{ $t('common.delBtn') }}
</el-button>
</template>
@ -59,65 +58,66 @@
</template>
<script lang="ts" setup>
import {BasicTableProps, useTable} from "/@/hooks/table";
import {delObj, fetchList} from "/@/api/admin/token";
import {useI18n} from 'vue-i18n'
import {useMessage, useMessageBox} from "/@/hooks/message";
import { BasicTableProps, useTable } from "/@/hooks/table";
import { delObj, fetchList } from "/@/api/admin/token";
import { useI18n } from 'vue-i18n'
import { useMessage, useMessageBox } from "/@/hooks/message";
import { Session } from "/@/utils/storage";
const {t} = useI18n()
//
const queryRef = ref()
const showSearch = ref(true)
const { t } = useI18n()
//
const queryRef = ref()
const showSearch = ref(true)
// rows
const selectObjs = ref([]) as any
//
const multiple = ref(true)
// rows
const selectObjs = ref([]) as any
//
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
username: ''
},
pageList: fetchList
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
username: ''
},
pageList: fetchList
});
// table hook
const {
getDataList,
currentChangeHandle,
sortChangeHandle,
sizeChangeHandle
} = useTable(state)
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (objs: any) => {
objs.forEach((val: any) => {
selectObjs.value.push(val.accessToken)
});
multiple.value = !objs.length
}
// table hook
const {
getDataList,
currentChangeHandle,
sortChangeHandle,
sizeChangeHandle
} = useTable(state)
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (objs: any) => {
objs.forEach((val: any) => {
selectObjs.value.push(val.accessToken)
});
multiple.value = !objs.length
}
//
const handleDelete = (accessTokens: string[]) => {
useMessageBox().confirm(t('common.delConfirmText'))
.then(() => {
delObj(accessTokens).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
//
const handleDelete = (accessTokens: string[]) => {
useMessageBox().confirm(t('common.delConfirmText'))
.then(() => {
delObj(accessTokens).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
};
</script>
})
};
<style scoped>
</style>
// token token
const filterOwnToken = (row: any) => {
return Session.get('token') === row.accessToken
}
</script>

View File

@ -1,8 +1,8 @@
<template>
<div class="system-user-dialog-container">
<el-dialog :title="dataForm.userId ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="dataForm" :rules="dataRules" label-width="90px" v-loading="loading">
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="dataForm" :rules="dataRules" label-width="90px" v-loading="loading">
<el-row :gutter="20">
<el-col :span="12" class="mb20">
<el-form-item :label="$t('sysuser.username')" prop="username">
@ -27,23 +27,22 @@
<el-col :span="12" class="mb20">
<el-form-item :label="$t('sysuser.role')" prop="role">
<el-select v-model="dataForm.role" placeholder="请选择角色" clearable class="w100" multiple>
<el-option v-for="item in roleData" :key="item.roleId" :label="item.roleName" :value="item.roleId"/>
<el-option v-for="item in roleData" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('sysuser.post')" prop="post">
<el-select v-model="dataForm.post" placeholder="请选择岗位" clearable class="w100" multiple>
<el-option v-for="item in postData" :key="item.postId" :label="item.postName" :value="item.postId"/>
<el-option v-for="item in postData" :key="item.postId" :label="item.postName" :value="item.postId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('sysuser.dept')" prop="dept">
<el-tree-select v-model="dataForm.deptId" :data="deptData"
:props="{ value: 'id', label: 'name', children: 'children' }" class="w100" clearable
check-strictly
placeholder="请选择所属部门">
:props="{ value: 'id', label: 'name', children: 'children' }" class="w100" clearable check-strictly
placeholder="请选择所属部门">
</el-tree-select>
</el-form-item>
</el-col>
@ -70,8 +69,8 @@
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false" >{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" >{{ $t('common.confirmButtonText') }}</el-button>
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
@ -79,21 +78,21 @@
</template>
<script setup lang="ts" name="systemUserDialog">
import {getObj, addObj, putObj, validateUsername, validatePhone} from '/@/api/admin/user'
import {list as roleList} from '/@/api/admin/role'
import {list as postList} from '/@/api/admin/post'
import {depttree} from '/@/api/admin/dept'
import {useDict} from "/@/hooks/dict";
import {useI18n} from "vue-i18n";
import {useMessage} from '/@/hooks/message';
import {rule} from '/@/utils/validate';
import { getObj, addObj, putObj, validateUsername, validatePhone } from '/@/api/admin/user'
import { list as roleList } from '/@/api/admin/role'
import { list as postList } from '/@/api/admin/post'
import { depttree } from '/@/api/admin/dept'
import { useDict } from "/@/hooks/dict";
import { useI18n } from "vue-i18n";
import { useMessage } from '/@/hooks/message';
import { rule } from '/@/utils/validate';
const {t} = useI18n()
const { t } = useI18n()
// emit
const emit = defineEmits(['refresh']);
// @ts-ignore
const {lock_flag} = useDict('lock_flag')
const { lock_flag } = useDict('lock_flag')
//
const dataFormRef = ref();
@ -123,43 +122,37 @@ const dataForm = reactive({
});
const dataRules = ref(
{
username: [{required: true, message: "用户名不能为空", trigger: "blur"}, {
min: 5,
max: 20,
message: "用户名称长度必须介于 5 和 20 之间",
trigger: "blur"
}, {
validator: (rule: any, value: any, callback: any) => {
validateUsername(rule, value, callback, dataForm.userId !== '')
}, trigger: 'blur'
}],
password: [{required: true, message: "密码不能为空", trigger: "blur"}, {
min: 6,
max: 20,
message: "用户密码长度必须介于 6 和 20 之间",
trigger: "blur"
}],
name: [{required: true, message: "姓名不能为空", trigger: "blur"}],
deptId: [{required: true, message: "部门不能为空", trigger: "blur"}],
role: [{required: true, message: "角色不能为空", trigger: "blur"}],
post: [{required: true, message: "岗位不能为空", trigger: "blur"}],
phone: [{required: true, message: "手机号不能为空", trigger: "blur"}, {
validator: rule.validatePhone,
trigger: 'blur'
}, {
validator: {
validator: (rule: any, value: any, callback: any) => {
validatePhone(rule, value, callback, dataForm.userId !== '')
}, trigger: 'blur'
}, trigger: 'blur'
}],
email: [{type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"]}]
}
{
// 5-20
username: [{ required: true, message: "用户名不能为空", trigger: "blur" }
, { min: 5, max: 20, message: "用户名称长度必须介于 5 和 20 之间", trigger: "blur" }
, {
validator: (rule: any, value: any, callback: any) => {
validateUsername(rule, value, callback, dataForm.userId !== '')
}, trigger: 'blur'
}],
password: [{ required: true, message: "密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }],
//
name: [{ required: true, message: "姓名不能为空", trigger: "blur" }
, { validator: rule.chinese, trigger: 'blur' }
],
deptId: [{ required: true, message: "部门不能为空", trigger: "blur" }],
role: [{ required: true, message: "角色不能为空", trigger: "blur" }],
post: [{ required: true, message: "岗位不能为空", trigger: "blur" }],
//
phone: [{ required: true, message: "手机号不能为空", trigger: "blur" }
, { validator: rule.validatePhone, trigger: 'blur' }
, {
validator: (rule: any, value: any, callback: any) => {
validatePhone(rule, value, callback, dataForm.userId !== '')
}, trigger: 'blur'
}],
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }]
}
)
//
const openDialog = (id: string) => {
const openDialog = async (id: string) => {
visible.value = true
dataForm.userId = ''
@ -171,7 +164,8 @@ const openDialog = (id: string) => {
//
if (id) {
dataForm.userId = id
getUserData(id)
await getUserData(id)
dataForm.password = '******'
}
// 使
@ -220,14 +214,13 @@ const onSubmit = () => {
})
}
})
};
//
const getUserData = (id: string) => {
//
loading.value = true
getObj(id).then(res => {
return getObj(id).then(res => {
Object.assign(dataForm, res.data)
if (res.data.roleList) {
dataForm.role = []

View File

@ -4,9 +4,8 @@
<el-row class="mb8" v-show="showSearch">
<el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
<el-form-item :label="$t('datasourceconf.dsName')" prop="dsName">
<el-input :placeholder="$t('datasourceconf.inputdsNameTip')" formDialogRef
style="max-width: 180px"
v-model="state.queryForm.dsName"/>
<el-input :placeholder="$t('datasourceconf.inputdsNameTip')" formDialogRef style="max-width: 180px"
v-model="state.queryForm.dsName" />
</el-form-item>
<el-form-item class="ml2">
<el-button @click="getDataList" icon="search" type="primary">
@ -23,117 +22,116 @@
{{ $t('common.addBtn') }}
</el-button>
<el-button :disabled="multiple" @click="handleDelete(undefined)" class="ml10" icon="Delete"
type="primary">
type="primary">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar @queryTable="getDataList" class="ml10" style="float: right;margin-right: 20px"
v-model:showSearch="showSearch"></right-toolbar>
v-model:showSearch="showSearch"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" @selection-change="handleSelectionChange" style="width: 100%"
v-loading="state.loading">
<el-table-column align="center" type="selection" width="50"/>
<el-table-column :label="t('datasourceconf.index')" type="index" width="80"/>
<el-table-column :label="t('datasourceconf.name')" prop="name" show-overflow-tooltip/>
<el-table-column :label="t('datasourceconf.dsName')" prop="dsName" show-overflow-tooltip/>
<el-table-column :label="t('datasourceconf.dsType')" prop="dsType" show-overflow-tooltip/>
<el-table-column :label="t('datasourceconf.username')" prop="username" show-overflow-tooltip/>
<el-table-column :label="t('datasourceconf.createTime')" prop="createTime" show-overflow-tooltip/>
v-loading="state.loading">
<el-table-column align="center" type="selection" width="50" />
<el-table-column :label="t('datasourceconf.index')" type="index" width="80" />
<el-table-column :label="t('datasourceconf.name')" prop="name" show-overflow-tooltip />
<el-table-column :label="t('datasourceconf.dsName')" prop="dsName" show-overflow-tooltip />
<el-table-column :label="t('datasourceconf.dsType')" prop="dsType" show-overflow-tooltip />
<el-table-column :label="t('datasourceconf.username')" prop="username" show-overflow-tooltip />
<el-table-column :label="t('datasourceconf.createTime')" prop="createTime" show-overflow-tooltip />
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-button @click="downloadDoc(scope.row.name)" text type="primary">{{
$t('datasourceconf.docBtn')
}}
}}
</el-button>
<el-button @click="formDialogRef.openDialog(scope.row.id)" text type="primary">{{
$t('common.editBtn')
}}
}}
</el-button>
<el-button @click="handleDelete(scope.row)" text type="primary">{{
$t('common.delBtn')
}}
}}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle"
v-bind="state.pagination"/>
<pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" />
</el-card>
<!-- 编辑新增 -->
<form-dialog @refresh="getDataList()" ref="formDialogRef"/>
<form-dialog @refresh="getDataList()" ref="formDialogRef" />
</div>
</template>
<script lang="ts" name="systemDatasourceConf" setup>
import {BasicTableProps, useTable} from "/@/hooks/table";
import {delObj, fetchList} from "/@/api/gen/datasource";
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
import {downBlobFile} from "/@/utils/other";
import { BasicTableProps, useTable } from "/@/hooks/table";
import { delObj, fetchList } from "/@/api/gen/datasource";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useI18n } from "vue-i18n";
import { downBlobFile } from "/@/utils/other";
//
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const {t} = useI18n()
//
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const { t } = useI18n()
//
const formDialogRef = ref()
//
const queryRef = ref()
const showSearch = ref(true)
//
const selectObjs = ref([])
const multiple = ref(true)
//
const formDialogRef = ref()
//
const queryRef = ref()
const showSearch = ref(true)
//
const selectObjs = ref([])
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
} = useTable(state)
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
} = useTable(state)
const downloadDoc = (dsName: string) => {
downBlobFile('/gen/dsconf/doc', {dsName}, `${dsName}.html`)
const downloadDoc = (dsName: string) => {
downBlobFile('/gen/dsconf/doc', { dsName }, `${dsName}.html`)
}
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (val: any) => {
selectObjs.value = val
multiple.value = !val.length
}
//
const handleDelete = (row: any) => {
if (!row) {
selectObjs.value.forEach((val: any) => {
handleDelete(val)
});
return
}
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (val: any) => {
selectObjs.value = val
multiple.value = !val.length
}
//
const handleDelete = (row: any) => {
if (!row) {
selectObjs.value.forEach((val: any) => {
handleDelete(val)
});
return
}
useMessageBox().confirm(t('common.delConfirmText') + row.id)
.then(() => {
delObj(row.id).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
useMessageBox().confirm(t('common.delConfirmText') + row.id)
.then(() => {
delObj(row.id).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
};
})
};
</script>

View File

@ -13,7 +13,7 @@ onMounted(async () => {
// code ticket
let code = other.getQueryString(url, 'code')
if (rule.validatenull(code)) {
if (rule.validateNull(code)) {
code = other.getQueryString(url, 'ticket')
}