Merge pull request !222 from xingyu/master
pull/2/head
芋道源码 2022-07-21 09:55:21 +00:00 committed by Gitee
commit 6691c08585
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
28 changed files with 256 additions and 218 deletions

View File

@ -94,6 +94,19 @@ public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {
return this; return this;
} }
public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
if (values!= null && values.length >0 && values[0] != null && values[1] != null) {
return (LambdaQueryWrapperX<T>) super.between(column, values[0], values[1]);
}
if (values != null && values[0] != null) {
return (LambdaQueryWrapperX<T>) ge(column, values[0]);
}
if (values != null && values[1] != null) {
return (LambdaQueryWrapperX<T>) le(column, values[2]);
}
return this;
}
// ========== 重写父类方法,方便链式调用 ========== // ========== 重写父类方法,方便链式调用 ==========
@Override @Override

View File

@ -37,6 +37,10 @@ public class UserPageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime; private Date endTime;
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date[] createTime;
@ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门") @ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门")
private Long deptId; private Long deptId;

View File

@ -33,7 +33,8 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername()) .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile()) .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus()) .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()) .betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getBeginTime(),reqVO.getEndTime())
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
.inIfPresent(AdminUserDO::getDeptId, deptIds) .inIfPresent(AdminUserDO::getDeptId, deptIds)
.orderByDesc(AdminUserDO::getId)); .orderByDesc(AdminUserDO::getId));

View File

@ -1,6 +1,6 @@
{ {
"name": "ruoyi-vue-pro-vue3", "name": "ruoyi-vue-pro-vue3",
"version": "1.0.160", "version": "1.6.2.1601",
"description": "基于vue3、element-plus、typesScript、vite3", "description": "基于vue3、element-plus、typesScript、vite3",
"author": "xingyu", "author": "xingyu",
"private": false, "private": false,
@ -56,7 +56,7 @@
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.0.3", "@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3", "@commitlint/config-conventional": "^17.0.3",
"@iconify/json": "^2.1.79", "@iconify/json": "^2.1.80",
"@intlify/vite-plugin-vue-i18n": "^5.0.0", "@intlify/vite-plugin-vue-i18n": "^5.0.0",
"@purge-icons/generated": "^0.8.1", "@purge-icons/generated": "^0.8.1",
"@types/intro.js": "^5.1.0", "@types/intro.js": "^5.1.0",

View File

@ -23,3 +23,21 @@ export const getKeyListApi = (keyTemplate: string) => {
} }
}) })
} }
// 获取缓存内容
export const getKeyValue = (key: string) => {
return request.get({ url: '/infra/redis/get-key-value?key=' + key })
}
// 根据键名删除缓存
export const deleteKey = (key: string) => {
return request.delete({ url: '/infra/redis/delete-key?key=' + key })
}
export const deleteKeys = (keyTemplate: string) => {
return request.delete({
url: '/infra/redis/delete-keys?',
params: {
keyTemplate
}
})
}

View File

@ -1,10 +1,8 @@
// import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import type { Slots } from 'vue' import type { Slots } from 'vue'
import { getSlot } from '@/utils/tsxHelper' import { getSlot } from '@/utils/tsxHelper'
import { PlaceholderMoel } from './types' import { PlaceholderMoel } from './types'
// const { t } = useI18n()
/** /**
* *
* @param schema * @param schema
@ -12,12 +10,12 @@ import { PlaceholderMoel } from './types'
* @description placeholder * @description placeholder
*/ */
export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => { export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => {
const { t } = useI18n()
const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword'] const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword']
const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect'] const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect']
if (textMap.includes(schema?.component as string)) { if (textMap.includes(schema?.component as string)) {
return { return {
// placeholder: t('common.inputText') placeholder: t('common.inputText')
placeholder: '请输入'
} }
} }
if (selectMap.includes(schema?.component as string)) { if (selectMap.includes(schema?.component as string)) {
@ -29,16 +27,13 @@ export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => {
) )
) { ) {
return { return {
// startPlaceholder: t('common.startTimeText'), startPlaceholder: t('common.startTimeText'),
// endPlaceholder: t('common.endTimeText'), endPlaceholder: t('common.endTimeText'),
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
rangeSeparator: '-' rangeSeparator: '-'
} }
} else { } else {
return { return {
// placeholder: t('common.selectText') placeholder: t('common.selectText')
placeholder: '请选择'
} }
} }
} }

View File

@ -59,7 +59,7 @@ watch(
:class="[ :class="[
prefixCls, prefixCls,
layout !== 'classic' ? `${prefixCls}__Top` : '', layout !== 'classic' ? `${prefixCls}__Top` : '',
'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative', 'flex !h-[var(--logo-height)] items-center cursor-pointer justify-center relative',
'dark:bg-[var(--el-bg-color)]' 'dark:bg-[var(--el-bg-color)]'
]" ]"
to="/" to="/"

View File

@ -43,7 +43,7 @@ const loginOut = () => {
.catch(() => {}) .catch(() => {})
} }
const toProfile = async () => { const toProfile = async () => {
push('/user/profile') push('/userinfo/profile')
} }
const toDocument = () => { const toDocument = () => {
window.open('https://doc.iocoder.cn/') window.open('https://doc.iocoder.cn/')

View File

@ -5,7 +5,6 @@ import { config } from '@/config/axios/config'
import { getAccessToken, getRefreshToken, getTenantId } from '@/utils/auth' import { getAccessToken, getRefreshToken, getTenantId } from '@/utils/auth'
import errorCode from './errorCode' import errorCode from './errorCode'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
const BASE_URL = import.meta.env.VITE_BASE_URL const BASE_URL = import.meta.env.VITE_BASE_URL
@ -46,25 +45,27 @@ service.interceptors.request.use(
const tenantId = getTenantId() const tenantId = getTenantId()
if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId
} }
const params = config.params || {}
const data = config.data || false
if ( if (
config.method === 'post' && config.method?.toUpperCase() === 'POST' &&
config!.headers!['Content-Type'] === 'application/x-www-form-urlencoded' config!.headers!['Content-Type'] === 'application/x-www-form-urlencoded'
) { ) {
config.data = qs.stringify(config.data) config.data = qs.stringify(data)
} }
// get参数编码 // get参数编码
if (config.method === 'get' && config.params) { if (config.method?.toUpperCase() === 'GET' && config.params) {
let url = config.url as string let url = config.url as string
url += '?'
const keys = Object.keys(config.params)
for (const key of keys) {
if (config.params[key] !== void 0 && config.params[key] !== null) {
url += `${key}=${encodeURIComponent(config.params[key])}&`
}
}
// 给 get 请求加上时间戳参数,避免从缓存中拿数据 // 给 get 请求加上时间戳参数,避免从缓存中拿数据
// const now = new Date().getTime() // const now = new Date().getTime()
// url = url.substring(0, url.length - 1) + `?_t=${now}` // params = params.substring(0, url.length - 1) + `?_t=${now}`
url += '?'
const keys = Object.keys(params)
for (const key of keys) {
if (params[key] !== void 0 && params[key] !== null) {
url += `${key}=${encodeURIComponent(params[key])}&`
}
}
config.params = {} config.params = {}
config.url = url config.url = url
} }
@ -85,6 +86,7 @@ service.interceptors.response.use(
// 返回“[HTTP]请求没有返回值”; // 返回“[HTTP]请求没有返回值”;
throw new Error() throw new Error()
} }
const { t } = useI18n()
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = data.code || result_code const code = data.code || result_code
// 获取错误信息 // 获取错误信息
@ -134,6 +136,7 @@ service.interceptors.response.use(
(error: AxiosError) => { (error: AxiosError) => {
console.log('err' + error) // for debug console.log('err' + error) // for debug
let { message } = error let { message } = error
const { t } = useI18n()
if (message === 'Network Error') { if (message === 'Network Error') {
message = t('sys.api.errorMessage') message = t('sys.api.errorMessage')
} else if (message.includes('timeout')) { } else if (message.includes('timeout')) {
@ -146,6 +149,7 @@ service.interceptors.response.use(
} }
) )
function handleAuthorized() { function handleAuthorized() {
const { t } = useI18n()
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true isRelogin.show = true
ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {

View File

@ -0,0 +1,71 @@
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
import { useI18n } from './useI18n'
export const useMessage = () => {
const { t } = useI18n()
return {
// 消息提示
info(content: string) {
ElMessage.info(content)
},
// 错误消息
error(content: string) {
ElMessage.error(content)
},
// 成功消息
success(content: string) {
ElMessage.success(content)
},
// 警告消息
warning(content: string) {
ElMessage.warning(content)
},
// 弹出提示
alert(content: string) {
ElMessageBox.alert(content, t('common.confirmTitle'))
},
// 错误提示
alertError(content: string) {
ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'error' })
},
// 成功提示
alertSuccess(content: string) {
ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'success' })
},
// 警告提示
alertWarning(content: string) {
ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'warning' })
},
// 通知提示
notify(content: string) {
ElNotification.info(content)
},
// 错误通知
notifyError(content: string) {
ElNotification.error(content)
},
// 成功通知
notifySuccess(content: string) {
ElNotification.success(content)
},
// 警告通知
notifyWarning(content: string) {
ElNotification.warning(content)
},
// 确认窗体
confirm(content: string, tip: string) {
return ElMessageBox.confirm(content, tip, {
confirmButtonText: t('common.ok'),
cancelButtonText: t('common.cancel'),
type: 'warning'
})
},
// 提交内容
prompt(content: string, tip: string) {
return ElMessageBox.prompt(content, tip, {
confirmButtonText: t('common.ok'),
cancelButtonText: t('common.cancel'),
type: 'warning'
})
}
}
}

View File

@ -41,7 +41,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
] ]
}, },
{ {
path: '/user', path: '/userinfo',
component: Layout, component: Layout,
name: 'UserInfo', name: 'UserInfo',
meta: { meta: {

View File

@ -8,7 +8,8 @@ import type { ApiErrorLogVO } from '@/api/infra/apiErrorLog/types'
import { allSchemas } from './apiErrorLog.data' import { allSchemas } from './apiErrorLog.data'
import * as ApiErrorLogApi from '@/api/infra/apiErrorLog' import * as ApiErrorLogApi from '@/api/infra/apiErrorLog'
import { InfraApiErrorLogProcessStatusEnum } from '@/utils/constants' import { InfraApiErrorLogProcessStatusEnum } from '@/utils/constants'
import { ElMessage, ElMessageBox } from 'element-plus' import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() // const { t } = useI18n() //
// ========== ========== // ========== ==========
@ -36,14 +37,11 @@ const handleDetail = (row: ApiErrorLogVO) => {
} }
// //
const handleProcessClick = (row: ApiErrorLogVO, processSttatus: number, type: string) => { const handleProcessClick = (row: ApiErrorLogVO, processSttatus: number, type: string) => {
ElMessageBox.confirm('确认标记为' + type + '?', t('common.reminder'), { message
confirmButtonText: t('common.ok'), .confirm('确认标记为' + type + '?', t('common.reminder'))
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(async () => { .then(async () => {
ApiErrorLogApi.updateApiErrorLogPageApi(row.id, processSttatus).then(() => { ApiErrorLogApi.updateApiErrorLogPageApi(row.id, processSttatus).then(() => {
ElMessage.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
getList() getList()
}) })
}) })

View File

@ -10,7 +10,8 @@ import ImportTable from './components/ImportTable.vue'
import Preview from './components/Preview.vue' import Preview from './components/Preview.vue'
import download from '@/utils/download' import download from '@/utils/download'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus' import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() // const { t } = useI18n() //
const { push } = useRouter() const { push } = useRouter()
// ========== ========== // ========== ==========
@ -37,14 +38,12 @@ const handleEditTable = (row: CodegenTableVO) => {
const handleSynchDb = (row: CodegenTableVO) => { const handleSynchDb = (row: CodegenTableVO) => {
// DB // DB
const tableName = row.tableName const tableName = row.tableName
ElMessageBox.confirm('确认要强制同步' + tableName + '表结构吗?', t('common.reminder'), { message
confirmButtonText: t('common.ok'), .confirm('确认要强制同步' + tableName + '表结构吗?', t('common.reminder'))
cancelButtonText: t('common.cancel'), .then(async () => {
type: 'warning' await CodegenApi.syncCodegenFromDBApi(row.id)
}).then(async () => { message.success('同步成功')
await CodegenApi.syncCodegenFromDBApi(row.id) })
ElMessage.success('同步成功')
})
} }
// //
const handleGenTable = (row: CodegenTableVO) => { const handleGenTable = (row: CodegenTableVO) => {

View File

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, unref } from 'vue' import { ref, unref } from 'vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE } from '@/utils/dict'
import { useTable } from '@/hooks/web/useTable' import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
@ -9,6 +8,8 @@ import { FormExpose } from '@/components/Form'
import type { FileConfigVO } from '@/api/infra/fileConfig/types' import type { FileConfigVO } from '@/api/infra/fileConfig/types'
import { rules, allSchemas } from './fileConfig.data' import { rules, allSchemas } from './fileConfig.data'
import * as FileConfigApi from '@/api/infra/fileConfig' import * as FileConfigApi from '@/api/infra/fileConfig'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() // const { t } = useI18n() //
// ========== ========== // ========== ==========
@ -49,16 +50,12 @@ const handleUpdate = async (row: FileConfigVO) => {
// //
const handleMaster = (row: FileConfigVO) => { const handleMaster = (row: FileConfigVO) => {
ElMessageBox.confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder'), { message
confirmButtonText: t('common.ok'), .confirm('是否确认修改配置【 ' + row.name + ' 】为主配置?', t('common.reminder'))
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(async () => { .then(async () => {
await FileConfigApi.updateFileConfigMasterApi(row.id) await FileConfigApi.updateFileConfigMasterApi(row.id)
await getList() await getList()
}) })
.catch(() => {})
} }
// //
@ -69,10 +66,10 @@ const submitForm = async () => {
const data = unref(formRef)?.formModel as FileConfigVO const data = unref(formRef)?.formModel as FileConfigVO
if (actionType.value === 'create') { if (actionType.value === 'create') {
await FileConfigApi.createFileConfigApi(data) await FileConfigApi.createFileConfigApi(data)
ElMessage.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await FileConfigApi.updateFileConfigApi(data) await FileConfigApi.updateFileConfigApi(data)
ElMessage.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
// //
dialogVisible.value = false dialogVisible.value = false

View File

@ -9,8 +9,9 @@ import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { FormExpose } from '@/components/Form' import { FormExpose } from '@/components/Form'
import { rules, allSchemas } from './job.data' import { rules, allSchemas } from './job.data'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() // const { t } = useI18n() //
const { push } = useRouter() const { push } = useRouter()
// ========== ========== // ========== ==========
@ -64,18 +65,11 @@ const handleJobLog = (row: JobVO) => {
} }
// //
const handleRun = (row: JobVO) => { const handleRun = (row: JobVO) => {
ElMessageBox.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder'), { message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => {
confirmButtonText: t('common.ok'), await JobApi.runJobApi(row.id)
cancelButtonText: t('common.cancel'), message.success('执行成功')
type: 'warning' getList()
}) })
.then(async () => {
JobApi.runJobApi(row.id).then(() => {
ElMessage.success('执行成功')
getList()
})
})
.catch(() => {})
} }
// //
const submitForm = async () => { const submitForm = async () => {
@ -85,10 +79,10 @@ const submitForm = async () => {
const data = unref(formRef)?.formModel as JobVO const data = unref(formRef)?.formModel as JobVO
if (actionType.value === 'create') { if (actionType.value === 'create') {
await JobApi.createJobApi(data) await JobApi.createJobApi(data)
ElMessage.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await JobApi.updateJobApi(data) await JobApi.updateJobApi(data)
ElMessage.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
// //
dialogVisible.value = false dialogVisible.value = false

View File

@ -1,12 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { ElInput, ElCard, ElTree, ElTreeSelect, ElMessage, ElMessageBox } from 'element-plus' import { ElInput, ElCard, ElTree, ElTreeSelect } from 'element-plus'
import { handleTree } from '@/utils/tree' import { handleTree } from '@/utils/tree'
import { onMounted, ref, unref, watch } from 'vue' import { onMounted, ref, unref, watch } from 'vue'
import * as DeptApi from '@/api/system/dept' import * as DeptApi from '@/api/system/dept'
import { Form, FormExpose } from '@/components/Form' import { Form, FormExpose } from '@/components/Form'
import { modelSchema } from './dept.data' import { modelSchema } from './dept.data'
import { DeptVO } from '@/api/system/dept/types' import { DeptVO } from '@/api/system/dept/types'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
interface Tree { interface Tree {
id: number id: number
name: string name: string
@ -29,10 +31,10 @@ const formRef = ref<FormExpose>()
// ========== ========== // ========== ==========
const filterText = ref('') const filterText = ref('')
const deptOptions = ref([]) // const deptOptions = ref() //
const treeRef = ref<InstanceType<typeof ElTree>>() const treeRef = ref<InstanceType<typeof ElTree>>()
const getTree = async () => { const getTree = async () => {
const res = await DeptApi.listSimpleDeptApi() const res = await DeptApi.getDeptPageApi(null)
deptOptions.value = handleTree(res) deptOptions.value = handleTree(res)
} }
const filterNode = (value: string, data: Tree) => { const filterNode = (value: string, data: Tree) => {
@ -60,14 +62,11 @@ const handleUpdate = async (data: { id: number }) => {
} }
// //
const handleDelete = async (data: { id: number }) => { const handleDelete = async (data: { id: number }) => {
ElMessageBox.confirm(t('common.delDataMessage'), t('common.confirmTitle'), { message
confirmButtonText: t('common.ok'), .confirm(t('common.delDataMessage'), t('common.confirmTitle'))
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(async () => { .then(async () => {
await DeptApi.deleteDeptApi(data.id) await DeptApi.deleteDeptApi(data.id)
ElMessage.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
}) })
.catch(() => {}) .catch(() => {})
await getTree() await getTree()
@ -118,6 +117,7 @@ onMounted(async () => {
:highlight-current="true" :highlight-current="true"
default-expand-all default-expand-all
:filter-node-method="filterNode" :filter-node-method="filterNode"
:expand-on-click-node="false"
> >
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">

View File

@ -56,26 +56,13 @@ const crudSchemas = reactive<CrudSchema[]>([
field: 'createTime', field: 'createTime',
form: { form: {
show: false show: false
}
},
{
label: t('common.createTime'),
field: 'daterange',
table: {
show: false
},
form: {
show: false
},
detail: {
show: false
}, },
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -54,26 +54,13 @@ const crudSchemas = reactive<CrudSchema[]>([
field: 'createTime', field: 'createTime',
form: { form: {
show: false show: false
}
},
{
label: t('common.createTime'),
field: 'daterange',
table: {
show: false
},
form: {
show: false
},
detail: {
show: false
}, },
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -16,16 +16,16 @@ import {
ElInput, ElInput,
ElInputNumber, ElInputNumber,
ElSelect, ElSelect,
ElTreeSelect,
ElOption, ElOption,
ElMessageBox,
ElMessage,
ElCascader,
ElRadioGroup, ElRadioGroup,
ElRadioButton ElRadioButton
} from 'element-plus' } from 'element-plus'
import { MenuVO } from '@/api/system/menu/types' import { MenuVO } from '@/api/system/menu/types'
import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() // const { t } = useI18n() //
// ========== ========== // ========== ==========
const loading = ref(true) const loading = ref(true)
@ -41,10 +41,13 @@ const menuProps = {
label: 'name', label: 'name',
value: 'id' value: 'id'
} }
const menuOptions = ref([]) // const menuOptions = ref() //
const getTree = async () => { const getTree = async () => {
const res = await MenuApi.listSimpleMenusApi() const res = await MenuApi.listSimpleMenusApi()
menuOptions.value = handleTree(res) const menu = { id: 0, name: '主类目', children: [] }
menu.children = handleTree(res)
console.info(menu)
menuOptions.value = menu
} }
// ========== ========== // ========== ==========
const queryParams = reactive({ const queryParams = reactive({
@ -108,14 +111,11 @@ const handleUpdate = async (row: MenuVO) => {
} }
// //
const handleDelete = async (row: MenuVO) => { const handleDelete = async (row: MenuVO) => {
ElMessageBox.confirm(t('common.delDataMessage'), t('common.confirmTitle'), { message
confirmButtonText: t('common.ok'), .confirm(t('common.delDataMessage'), t('common.confirmTitle'))
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(async () => { .then(async () => {
await MenuApi.deleteMenuApi(row.id) await MenuApi.deleteMenuApi(row.id)
ElMessage.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
}) })
.catch(() => {}) .catch(() => {})
await getList() await getList()
@ -134,20 +134,20 @@ const submitForm = async () => {
) { ) {
if (!isExternal(menuForm.value.path)) { if (!isExternal(menuForm.value.path)) {
if (menuForm.value.parentId === 0 && menuForm.value.path.charAt(0) !== '/') { if (menuForm.value.parentId === 0 && menuForm.value.path.charAt(0) !== '/') {
ElMessage.error('路径必须以 / 开头') message.error('路径必须以 / 开头')
return return
} else if (menuForm.value.parentId !== 0 && menuForm.value.path.charAt(0) === '/') { } else if (menuForm.value.parentId !== 0 && menuForm.value.path.charAt(0) === '/') {
ElMessage.error('路径不能以 / 开头') message.error('路径不能以 / 开头')
return return
} }
} }
} }
if (actionType.value === 'create') { if (actionType.value === 'create') {
await MenuApi.createMenuApi(menuForm.value) await MenuApi.createMenuApi(menuForm.value)
ElMessage.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await MenuApi.updateMenuApi(menuForm.value) await MenuApi.updateMenuApi(menuForm.value)
ElMessage.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
// //
dialogVisible.value = false dialogVisible.value = false
@ -264,13 +264,12 @@ onMounted(async () => {
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="上级菜单"> <el-form-item label="上级菜单">
<el-cascader <el-tree-select
:options="menuData" node-key="id"
:props="menuProps"
placeholder="请选择上级菜单"
v-model="menuForm.parentId" v-model="menuForm.parentId"
class="w-100" :props="menuProps"
clearable :data="menuData"
check-strictly
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, unref } from 'vue' import { ref, unref } from 'vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ElMessage, ElImage } from 'element-plus' import { ElMessage, ElImage, ElTag } from 'element-plus'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE } from '@/utils/dict'
import { useTable } from '@/hooks/web/useTable' import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
@ -118,6 +118,16 @@ getList()
<template #status="{ row }"> <template #status="{ row }">
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
</template> </template>
<template #authorizedGrantTypes="{ row }">
<el-tag
:disable-transitions="true"
:key="index"
v-for="(authorizedGrantType, index) in row.authorizedGrantTypes"
:index="index"
>
{{ authorizedGrantType }}
</el-tag>
</template>
<template #createTime="{ row }"> <template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template> </template>

View File

@ -68,7 +68,7 @@ getList()
<span>{{ row.resultCode === 0 ? '成功' : '失败' }}</span> <span>{{ row.resultCode === 0 ? '成功' : '失败' }}</span>
</template> </template>
<template #startTime="{ row }"> <template #startTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> <span>{{ dayjs(row.startTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template> </template>
<template #action="{ row }"> <template #action="{ row }">
<el-button link type="primary" @click="handleDetail(row)"> <el-button link type="primary" @click="handleDetail(row)">

View File

@ -41,7 +41,10 @@ const crudSchemas = reactive<CrudSchema[]>([
}, },
{ {
label: '操作人员', label: '操作人员',
field: 'userNickname' field: 'userNickname',
search: {
show: true
}
}, },
{ {
label: '操作明细', label: '操作明细',
@ -63,40 +66,37 @@ const crudSchemas = reactive<CrudSchema[]>([
}, },
{ {
label: '操作结果', label: '操作结果',
field: 'resultCode' field: 'resultCode',
search: {
show: true,
component: 'Select',
componentProps: {
options: [
{ label: '成功', value: true },
{ label: '失败', value: false }
]
}
}
}, },
{ {
label: '操作日期', label: '操作日期',
field: 'startTime', field: 'startTime',
form: { form: {
show: false show: false
}
},
{
label: '执行时长',
field: 'duration'
},
{
label: '操作日期',
field: 'daterange',
table: {
show: false
},
form: {
show: false
},
detail: {
show: false
}, },
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },
{
label: '执行时长',
field: 'duration'
},
{ {
label: t('table.action'), label: t('table.action'),
field: 'action', field: 'action',

View File

@ -65,12 +65,15 @@ const crudSchemas = reactive<CrudSchema[]>([
form: { form: {
show: false show: false
}, },
detail: {
show: false
},
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -66,26 +66,13 @@ const crudSchemas = reactive<CrudSchema[]>([
field: 'createTime', field: 'createTime',
form: { form: {
show: false show: false
}
},
{
label: t('common.createTime'),
field: 'daterange',
table: {
show: false
},
form: {
show: false
},
detail: {
show: false
}, },
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -77,16 +77,6 @@ const crudSchemas = reactive<CrudSchema[]>([
{ {
label: t('common.createTime'), label: t('common.createTime'),
field: 'createTime', field: 'createTime',
form: {
show: false
}
},
{
label: '接收时间',
field: 'daterange',
table: {
show: false
},
form: { form: {
show: false show: false
}, },
@ -94,8 +84,8 @@ const crudSchemas = reactive<CrudSchema[]>([
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -77,26 +77,13 @@ const crudSchemas = reactive<CrudSchema[]>([
field: 'createTime', field: 'createTime',
form: { form: {
show: false show: false
}
},
{
label: t('common.createTime'),
field: 'daterange',
table: {
show: false
},
form: {
show: false
},
detail: {
show: false
}, },
search: { search: {
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }
}, },

View File

@ -3,7 +3,6 @@ import { onMounted, ref, unref, watch } from 'vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { import {
ElInput, ElInput,
ElMessage,
ElCard, ElCard,
ElTree, ElTree,
ElTreeSelect, ElTreeSelect,
@ -14,7 +13,6 @@ import {
ElUpload, ElUpload,
ElSwitch, ElSwitch,
ElCheckbox, ElCheckbox,
ElMessageBox,
UploadInstance, UploadInstance,
UploadRawFile UploadRawFile
} from 'element-plus' } from 'element-plus'
@ -32,6 +30,8 @@ import * as UserApi from '@/api/system/user'
import download from '@/utils/download' import download from '@/utils/download'
import { CommonStatusEnum } from '@/utils/constants' import { CommonStatusEnum } from '@/utils/constants'
import { getAccessToken, getTenantId } from '@/utils/auth' import { getAccessToken, getTenantId } from '@/utils/auth'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
interface Tree { interface Tree {
id: number id: number
name: string name: string
@ -127,10 +127,10 @@ const submitForm = async () => {
data.postIds = postIds.value data.postIds = postIds.value
if (actionType.value === 'create') { if (actionType.value === 'create') {
await UserApi.createUserApi(data) await UserApi.createUserApi(data)
ElMessage.success(t('common.createSuccess')) message.success(t('common.createSuccess'))
} else { } else {
await UserApi.updateUserApi(data) await UserApi.updateUserApi(data)
ElMessage.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
} }
// //
dialogVisible.value = false dialogVisible.value = false
@ -142,16 +142,13 @@ const submitForm = async () => {
// //
const handleStatusChange = async (row: UserVO) => { const handleStatusChange = async (row: UserVO) => {
const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用' const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用'
ElMessageBox.confirm('确认要"' + text + '""' + row.username + '"用户吗?', t('common.reminder'), { message
confirmButtonText: t('common.ok'), .confirm('确认要"' + text + '""' + row.username + '"用户吗?', t('common.reminder'))
cancelButtonText: t('common.cancel'),
type: 'warning'
})
.then(async () => { .then(async () => {
row.status = row.status =
row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.ENABLE : CommonStatusEnum.DISABLE row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.ENABLE : CommonStatusEnum.DISABLE
await UserApi.updateUserStatusApi(row.id, row.status) await UserApi.updateUserStatusApi(row.id, row.status)
ElMessage.success(text + '成功') message.success(text + '成功')
await getList() await getList()
}) })
.catch(() => { .catch(() => {
@ -161,12 +158,9 @@ const handleStatusChange = async (row: UserVO) => {
} }
// //
const handleResetPwd = (row: UserVO) => { const handleResetPwd = (row: UserVO) => {
ElMessageBox.prompt('请输入"' + row.username + '"的新密码', t('common.reminder'), { message.prompt('请输入"' + row.username + '"的新密码', t('common.reminder')).then(({ value }) => {
confirmButtonText: t('common.ok'),
cancelButtonText: t('common.cancel')
}).then(({ value }) => {
UserApi.resetUserPwdApi(row.id, value).then(() => { UserApi.resetUserPwdApi(row.id, value).then(() => {
ElMessage.success('修改成功,新密码是:' + value) message.success('修改成功,新密码是:' + value)
}) })
}) })
} }
@ -207,8 +201,8 @@ const beforeExcelUpload = (file: UploadRawFile) => {
file.type === 'application/vnd.ms-excel' || file.type === 'application/vnd.ms-excel' ||
file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const isLt5M = file.size / 1024 / 1024 < 5 const isLt5M = file.size / 1024 / 1024 < 5
if (!isExcel) ElMessage.error('上传文件只能是 xls / xlsx 格式!') if (!isExcel) message.error('上传文件只能是 xls / xlsx 格式!')
if (!isLt5M) ElMessage.error('上传文件大小不能超过 5MB!') if (!isLt5M) message.error('上传文件大小不能超过 5MB!')
return isExcel && isLt5M return isExcel && isLt5M
} }
// //
@ -224,7 +218,7 @@ const submitFileForm = () => {
// //
const handleFileSuccess = (response: any): void => { const handleFileSuccess = (response: any): void => {
if (response.code !== 0) { if (response.code !== 0) {
ElMessage.error(response.msg) message.error(response.msg)
return return
} }
importDialogVisible.value = false importDialogVisible.value = false
@ -242,15 +236,15 @@ const handleFileSuccess = (response: any): void => {
for (const username in data.failureUsernames) { for (const username in data.failureUsernames) {
text += '< ' + username + ': ' + data.failureUsernames[username] + ' >' text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
} }
ElMessageBox.alert(text) message.alert(text)
} }
// //
const handleExceed = (): void => { const handleExceed = (): void => {
ElMessage.error('最多只能上传一个文件!') message.error('最多只能上传一个文件!')
} }
// //
const excelUploadError = (): void => { const excelUploadError = (): void => {
ElMessage.error('导入数据失败,请您重新上传!') message.error('导入数据失败,请您重新上传!')
} }
// ========== ========== // ========== ==========
onMounted(async () => { onMounted(async () => {

View File

@ -101,7 +101,7 @@ const crudSchemas = reactive<CrudSchema[]>([
}, },
{ {
label: t('common.createTime'), label: t('common.createTime'),
field: 'daterange', field: 'createTime',
table: { table: {
show: false show: false
}, },
@ -115,7 +115,7 @@ const crudSchemas = reactive<CrudSchema[]>([
show: true, show: true,
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
type: 'daterange', type: 'datetimerange',
valueFormat: 'YYYY-MM-DD HH:mm:ss' valueFormat: 'YYYY-MM-DD HH:mm:ss'
} }
} }