From b93491579c8afb85852faf5649976e8dcbc48642 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Fri, 14 Apr 2023 21:32:11 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E7=BB=99=E6=89=80=E6=9C=89=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=B7=BB=E5=8A=A0name=E5=B1=9E=E6=80=A7=E9=A2=84?= =?UTF-8?q?=E9=98=B2=E6=9C=AA=E7=9F=A5bug!!!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 4 +- src/components/Backtop/src/Backtop.vue | 2 +- .../ConfigGlobal/src/ConfigGlobal.vue | 4 +- .../src/ContentDetailWrap.vue | 10 +- .../ContentWrap/src/ContentWrap.vue | 4 +- src/components/CountTo/src/CountTo.vue | 2 +- src/components/Crontab/src/Crontab.vue | 102 ++++++++-------- src/components/Cropper/src/CopperModal.vue | 51 ++++---- src/components/Cropper/src/Cropper.vue | 4 +- src/components/Cropper/src/CropperAvatar.vue | 14 ++- .../Descriptions/src/Descriptions.vue | 10 +- src/components/Dialog/src/Dialog.vue | 18 +-- src/components/Echart/src/Echart.vue | 2 +- src/components/Editor/src/Editor.vue | 6 +- src/components/Error/src/Error.vue | 4 +- src/components/IFrame/src/IFrame.vue | 6 +- src/components/Icon/src/Icon.vue | 4 +- src/components/Icon/src/IconSelect.vue | 22 ++-- .../ImageViewer/src/ImageViewer.vue | 2 +- src/components/Infotip/src/Infotip.vue | 6 +- .../InputPassword/src/InputPassword.vue | 8 +- src/components/Pagination/index.vue | 10 +- src/components/Qrcode/src/Qrcode.vue | 9 +- src/components/Search/src/Search.vue | 24 ++-- src/components/Sticky/src/Sticky.vue | 5 +- src/components/Tooltip/src/Tooltip.vue | 3 +- src/components/Verifition/src/Verify.vue | 42 ++++--- .../Verifition/src/Verify/VerifyPoints.vue | 14 +-- .../Verifition/src/Verify/VerifySlide.vue | 22 ++-- src/components/XButton/src/XButton.vue | 7 +- src/components/XButton/src/XTextButton.vue | 7 +- src/layout/components/AppView.vue | 2 +- .../components/Collapse/src/Collapse.vue | 6 +- .../ContextMenu/src/ContextMenu.vue | 11 +- src/layout/components/Footer/src/Footer.vue | 2 +- .../LocaleDropdown/src/LocaleDropdown.vue | 8 +- src/layout/components/Logo/src/Logo.vue | 6 +- src/layout/components/Message/src/Message.vue | 19 ++- .../components/Screenfull/src/Screenfull.vue | 6 +- src/layout/components/Setting/src/Setting.vue | 16 +-- .../src/components/ColorRadioPicker.vue | 6 +- .../src/components/InterfaceDisplay.vue | 2 +- .../src/components/LayoutRadioPicker.vue | 2 +- .../SizeDropdown/src/SizeDropdown.vue | 4 +- .../components/TagsView/src/TagsView.vue | 39 ++++--- .../ThemeSwitch/src/ThemeSwitch.vue | 10 +- .../components/UserInfo/src/UserInfo.vue | 2 +- src/views/Error/403.vue | 2 +- src/views/Error/404.vue | 2 +- src/views/Error/500.vue | 2 +- src/views/Home/Index2.vue | 109 +++++++++--------- src/views/Login/Login.vue | 2 +- src/views/Login/components/LoginForm.vue | 42 +++---- src/views/Login/components/LoginFormTitle.vue | 2 +- src/views/Login/components/MobileForm.vue | 30 ++--- src/views/Login/components/QrCodeForm.vue | 8 +- src/views/Login/components/RegisterForm.vue | 20 ++-- src/views/Profile/components/BasicInfo.vue | 6 +- src/views/Profile/components/ProfileUser.vue | 31 +++-- src/views/Profile/components/ResetPwd.vue | 8 +- src/views/Profile/components/UserAvatar.vue | 11 +- src/views/bpm/form/editor/index.vue | 11 +- src/views/bpm/group/UserGroupForm.vue | 10 +- src/views/bpm/model/ModelForm.vue | 33 +++--- src/views/bpm/model/ModelImportForm.vue | 29 ++--- src/views/bpm/oa/leave/create.vue | 21 ++-- src/views/bpm/oa/leave/detail.vue | 6 +- .../detail/ProcessInstanceBpmnViewer.vue | 10 +- .../detail/ProcessInstanceTaskList.vue | 10 +- .../detail/TaskUpdateAssigneeForm.vue | 8 +- src/views/bpm/task/done/TaskDetail.vue | 6 +- .../bpm/taskAssignRule/TaskAssignRuleForm.vue | 39 ++++--- .../infra/apiAccessLog/ApiAccessLogDetail.vue | 10 +- .../infra/apiErrorLog/ApiErrorLogDetail.vue | 18 +-- src/views/infra/codegen/EditTable.vue | 5 +- src/views/infra/codegen/ImportTable.vue | 43 ++++--- src/views/infra/codegen/PreviewCode.vue | 29 ++--- .../codegen/components/BasicInfoForm.vue | 14 +-- .../codegen/components/ColumInfoForm.vue | 28 ++--- .../codegen/components/GenerateInfoForm.vue | 18 +-- src/views/infra/config/ConfigForm.vue | 10 +- .../dataSourceConfig/DataSourceConfigForm.vue | 8 +- src/views/infra/file/FileForm.vue | 29 ++--- src/views/infra/fileConfig/FileConfigForm.vue | 13 ++- src/views/infra/job/JobDetail.vue | 6 +- src/views/infra/job/logger/JobLogDetail.vue | 6 +- src/views/infra/webSocket/index.vue | 14 +-- .../mall/product/property/PropertyForm.vue | 11 +- .../mall/product/property/value/ValueForm.vue | 11 +- src/views/mp/account/AccountForm.vue | 11 +- .../mp/components/wx-editor/WxEditor.vue | 22 ++-- src/views/mp/components/wx-news/main.vue | 18 ++- src/views/mp/tag/TagForm.vue | 9 +- src/views/mp/user/UserForm.vue | 11 +- src/views/pay/app/AppForm.vue | 9 +- src/views/pay/merchant/MerchantForm.vue | 11 +- src/views/pay/order/OrderDetail.vue | 6 +- src/views/pay/refund/RefundDetail.vue | 6 +- src/views/system/area/AreaForm.vue | 11 +- src/views/system/dept/DeptForm.vue | 23 ++-- src/views/system/dict/DictTypeForm.vue | 13 ++- src/views/system/dict/data/DictDataForm.vue | 15 +-- src/views/system/errorCode/ErrorCodeForm.vue | 16 +-- src/views/system/loginlog/LoginLogDetail.vue | 6 +- .../system/mail/account/MailAccountDetail.vue | 6 +- .../system/mail/account/MailAccountForm.vue | 11 +- src/views/system/mail/log/MailLogDetail.vue | 6 +- .../system/mail/template/MailTemplateForm.vue | 13 ++- .../mail/template/MailTemplateSendForm.vue | 11 +- src/views/system/menu/MenuForm.vue | 67 +++++------ src/views/system/notice/NoticeForm.vue | 15 +-- .../notify/message/NotifyMessageDetail.vue | 6 +- .../notify/my/MyNotifyMessageDetail.vue | 8 +- src/views/system/oauth2/client/ClientForm.vue | 33 +++--- .../system/operatelog/OperateLogDetail.vue | 14 +-- src/views/system/post/PostForm.vue | 12 +- src/views/system/role/RoleAssignMenuForm.vue | 21 ++-- .../system/role/RoleDataPermissionForm.vue | 29 ++--- src/views/system/role/RoleForm.vue | 13 ++- src/views/system/role/index.vue | 101 ++++++++-------- .../sensitiveWord/SensitiveWordForm.vue | 13 ++- .../sensitiveWord/SensitiveWordTestForm.vue | 15 +-- src/views/system/sensitiveWord/index.vue | 90 ++++++++------- .../system/sms/channel/SmsChannelForm.vue | 11 +- src/views/system/sms/log/SmsLogDetail.vue | 6 +- .../system/sms/template/SmsTemplateForm.vue | 15 +-- .../sms/template/SmsTemplateSendForm.vue | 11 +- src/views/system/tenant/TenantForm.vue | 20 ++-- .../tenantPackage/TenantPackageForm.vue | 19 +-- src/views/system/user/DeptTree.vue | 10 +- src/views/system/user/UserAssignRoleForm.vue | 9 +- src/views/system/user/UserForm.vue | 19 +-- src/views/system/user/UserImportForm.vue | 28 ++--- 133 files changed, 1126 insertions(+), 993 deletions(-) diff --git a/src/App.vue b/src/App.vue index a7867a1c..75edd24f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="APP" setup> import { isDark } from '@/utils/is' import { useAppStore } from '@/store/modules/app' import { useDesign } from '@/hooks/web/useDesign' @@ -32,6 +32,7 @@ $prefix-cls: #{$namespace}-app; width: 100%; height: 100%; } + html, body { padding: 0 !important; @@ -43,6 +44,7 @@ body { @extend .size; } } + .#{$prefix-cls}-grey-mode { filter: grayscale(100%); } diff --git a/src/components/Backtop/src/Backtop.vue b/src/components/Backtop/src/Backtop.vue index f5c2fc44..70cf78cd 100644 --- a/src/components/Backtop/src/Backtop.vue +++ b/src/components/Backtop/src/Backtop.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="BackTop" setup> import { ElBacktop } from 'element-plus' import { useDesign } from '@/hooks/web/useDesign' diff --git a/src/components/ConfigGlobal/src/ConfigGlobal.vue b/src/components/ConfigGlobal/src/ConfigGlobal.vue index 10a0a9f2..20ff0357 100644 --- a/src/components/ConfigGlobal/src/ConfigGlobal.vue +++ b/src/components/ConfigGlobal/src/ConfigGlobal.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ConfigGlobal" setup> import { propTypes } from '@/utils/propTypes' import { useLocaleStore } from '@/store/modules/locale' import { useAppStore } from '@/store/modules/app' @@ -51,9 +51,9 @@ const currentLocale = computed(() => localeStore.currentLocale) <template> <ElConfigProvider - :namespace="variables.elNamespace" :locale="currentLocale.elLocale" :message="{ max: 1 }" + :namespace="variables.elNamespace" :size="size" > <slot></slot> diff --git a/src/components/ContentDetailWrap/src/ContentDetailWrap.vue b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue index 697ea18a..9469a552 100644 --- a/src/components/ContentDetailWrap/src/ContentDetailWrap.vue +++ b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ContentDetailWrap" setup> import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' @@ -21,7 +21,7 @@ onMounted(() => { </script> <template> - <div :class="[`${prefixCls}-container`]" ref="contentDetailWrap"> + <div ref="contentDetailWrap" :class="[`${prefixCls}-container`]"> <Sticky :offset="offset"> <div :class="[ @@ -31,7 +31,7 @@ onMounted(() => { > <div :class="[`${prefixCls}-header__back`, 'flex pl-10px pr-10px ']"> <ElButton @click="emit('back')"> - <Icon icon="ep:arrow-left" class="mr-5px" /> + <Icon class="mr-5px" icon="ep:arrow-left" /> {{ t('common.back') }} </ElButton> </div> @@ -47,7 +47,9 @@ onMounted(() => { </Sticky> <div style="padding: var(--app-content-padding)"> <ElCard :class="[`${prefixCls}-body`, 'mb-20px']" shadow="never"> - <div> <slot></slot> </div> + <div> + <slot></slot> + </div> </ElCard> </div> </div> diff --git a/src/components/ContentWrap/src/ContentWrap.vue b/src/components/ContentWrap/src/ContentWrap.vue index 6890e214..0fcfb16f 100644 --- a/src/components/ContentWrap/src/ContentWrap.vue +++ b/src/components/ContentWrap/src/ContentWrap.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ContentWrap" setup> import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' @@ -21,7 +21,7 @@ defineProps({ <template #content> <div class="max-w-200px">{{ message }}</div> </template> - <Icon class="ml-5px" icon="ep:question-filled" :size="14" /> + <Icon :size="14" class="ml-5px" icon="ep:question-filled" /> </ElTooltip> </div> </template> diff --git a/src/components/CountTo/src/CountTo.vue b/src/components/CountTo/src/CountTo.vue index 8d2f1ade..c4fa7b56 100644 --- a/src/components/CountTo/src/CountTo.vue +++ b/src/components/CountTo/src/CountTo.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="CountTo" setup> import { PropType } from 'vue' import { isNumber } from '@/utils/is' import { propTypes } from '@/utils/propTypes' diff --git a/src/components/Crontab/src/Crontab.vue b/src/components/Crontab/src/Crontab.vue index 0e474fb2..13096f75 100644 --- a/src/components/Crontab/src/Crontab.vue +++ b/src/components/Crontab/src/Crontab.vue @@ -1,10 +1,12 @@ -<script setup lang="ts"> +<script lang="ts" name="Crontab" setup> import { ElMessage } from 'element-plus' import { PropType } from 'vue' + interface shortcutsType { text: string value: string } + const props = defineProps({ modelValue: { type: String, @@ -501,7 +503,7 @@ const submit = () => { } </script> <template> - <el-input v-model="defaultValue" v-bind="$attrs" class="input-with-select"> + <el-input v-model="defaultValue" class="input-with-select" v-bind="$attrs"> <template #append> <el-select v-model="select" placeholder="生成器" style="width: 115px"> <el-option label="每分钟" value="0 * * * * ?" /> @@ -522,11 +524,11 @@ const submit = () => { </el-input> <el-dialog - title="cron规则生成器" v-model="dialogVisible" :width="580" - destroy-on-close append-to-body + destroy-on-close + title="cron规则生成器" > <div class="sc-cron"> <el-tabs> @@ -546,38 +548,38 @@ const submit = () => { <el-radio-button label="3">指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.second.type == '1'"> + <el-form-item v-if="cronValue.second.type == '1'" label="范围"> <el-input-number v-model="cronValue.second.range.start" - :min="0" :max="59" + :min="0" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.second.range.end" - :min="0" :max="59" + :min="0" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.second.type == '2'"> + <el-form-item v-if="cronValue.second.type == '2'" label="间隔"> <el-input-number v-model="cronValue.second.loop.start" - :min="0" :max="59" + :min="0" controls-position="right" /> 秒开始,每 <el-input-number v-model="cronValue.second.loop.end" - :min="0" :max="59" + :min="0" controls-position="right" /> 秒执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.second.type == '3'"> + <el-form-item v-if="cronValue.second.type == '3'" label="指定"> <el-select v-model="cronValue.second.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.second" @@ -605,38 +607,38 @@ const submit = () => { <el-radio-button label="3">指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.minute.type == '1'"> + <el-form-item v-if="cronValue.minute.type == '1'" label="范围"> <el-input-number v-model="cronValue.minute.range.start" - :min="0" :max="59" + :min="0" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.minute.range.end" - :min="0" :max="59" + :min="0" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.minute.type == '2'"> + <el-form-item v-if="cronValue.minute.type == '2'" label="间隔"> <el-input-number v-model="cronValue.minute.loop.start" - :min="0" :max="59" + :min="0" controls-position="right" /> 分钟开始,每 <el-input-number v-model="cronValue.minute.loop.end" - :min="0" :max="59" + :min="0" controls-position="right" /> 分钟执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.minute.type == '3'"> + <el-form-item v-if="cronValue.minute.type == '3'" label="指定"> <el-select v-model="cronValue.minute.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.minute" @@ -664,38 +666,38 @@ const submit = () => { <el-radio-button label="3">指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.hour.type == '1'"> + <el-form-item v-if="cronValue.hour.type == '1'" label="范围"> <el-input-number v-model="cronValue.hour.range.start" - :min="0" :max="23" + :min="0" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.hour.range.end" - :min="0" :max="23" + :min="0" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.hour.type == '2'"> + <el-form-item v-if="cronValue.hour.type == '2'" label="间隔"> <el-input-number v-model="cronValue.hour.loop.start" - :min="0" :max="23" + :min="0" controls-position="right" /> 小时开始,每 <el-input-number v-model="cronValue.hour.loop.end" - :min="0" :max="23" + :min="0" controls-position="right" /> 小时执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.hour.type == '3'"> + <el-form-item v-if="cronValue.hour.type == '3'" label="指定"> <el-select v-model="cronValue.hour.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.hour" @@ -725,38 +727,38 @@ const submit = () => { <el-radio-button label="5">不指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.day.type == '1'"> + <el-form-item v-if="cronValue.day.type == '1'" label="范围"> <el-input-number v-model="cronValue.day.range.start" - :min="1" :max="31" + :min="1" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.day.range.end" - :min="1" :max="31" + :min="1" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.day.type == '2'"> + <el-form-item v-if="cronValue.day.type == '2'" label="间隔"> <el-input-number v-model="cronValue.day.loop.start" - :min="1" :max="31" + :min="1" controls-position="right" /> 号开始,每 <el-input-number v-model="cronValue.day.loop.end" - :min="1" :max="31" + :min="1" controls-position="right" /> 天执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.day.type == '3'"> + <el-form-item v-if="cronValue.day.type == '3'" label="指定"> <el-select v-model="cronValue.day.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.day" @@ -784,38 +786,38 @@ const submit = () => { <el-radio-button label="3">指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.month.type == '1'"> + <el-form-item v-if="cronValue.month.type == '1'" label="范围"> <el-input-number v-model="cronValue.month.range.start" - :min="1" :max="12" + :min="1" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.month.range.end" - :min="1" :max="12" + :min="1" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.month.type == '2'"> + <el-form-item v-if="cronValue.month.type == '2'" label="间隔"> <el-input-number v-model="cronValue.month.loop.start" - :min="1" :max="12" + :min="1" controls-position="right" /> 月开始,每 <el-input-number v-model="cronValue.month.loop.end" - :min="1" :max="12" + :min="1" controls-position="right" /> 月执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.month.type == '3'"> + <el-form-item v-if="cronValue.month.type == '3'" label="指定"> <el-select v-model="cronValue.month.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.month" @@ -846,7 +848,7 @@ const submit = () => { <el-radio-button label="5">不指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.week.type == '1'"> + <el-form-item v-if="cronValue.week.type == '1'" label="范围"> <el-select v-model="cronValue.week.range.start"> <el-option v-for="(item, index) in data.week" @@ -865,12 +867,12 @@ const submit = () => { /> </el-select> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.week.type == '2'"> + <el-form-item v-if="cronValue.week.type == '2'" label="间隔"> 第 <el-input-number v-model="cronValue.week.loop.start" - :min="1" :max="4" + :min="1" controls-position="right" /> 周的星期 @@ -884,7 +886,7 @@ const submit = () => { </el-select> 执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.week.type == '3'"> + <el-form-item v-if="cronValue.week.type == '3'" label="指定"> <el-select v-model="cronValue.week.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.week" @@ -894,7 +896,7 @@ const submit = () => { /> </el-select> </el-form-item> - <el-form-item label="最后一周" v-if="cronValue.week.type == '4'"> + <el-form-item v-if="cronValue.week.type == '4'" label="最后一周"> <el-select v-model="cronValue.week.last"> <el-option v-for="(item, index) in data.week" @@ -924,12 +926,12 @@ const submit = () => { <el-radio-button label="3">指定</el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="范围" v-if="cronValue.year.type == '1'"> + <el-form-item v-if="cronValue.year.type == '1'" label="范围"> <el-input-number v-model="cronValue.year.range.start" controls-position="right" /> <span style="padding: 0 15px">-</span> <el-input-number v-model="cronValue.year.range.end" controls-position="right" /> </el-form-item> - <el-form-item label="间隔" v-if="cronValue.year.type == '2'"> + <el-form-item v-if="cronValue.year.type == '2'" label="间隔"> <el-input-number v-model="cronValue.year.loop.start" controls-position="right" /> 年开始,每 <el-input-number @@ -939,7 +941,7 @@ const submit = () => { /> 年执行一次 </el-form-item> - <el-form-item label="指定" v-if="cronValue.year.type == '3'"> + <el-form-item v-if="cronValue.year.type == '3'" label="指定"> <el-select v-model="cronValue.year.appoint" multiple style="width: 100%"> <el-option v-for="(item, index) in data.year" @@ -968,16 +970,19 @@ const submit = () => { padding: 0 7px; vertical-align: bottom; } + .sc-cron-num { text-align: center; margin-bottom: 15px; width: 100%; } + .sc-cron-num h2 { font-size: 12px; margin-bottom: 15px; font-weight: normal; } + .sc-cron-num h4 { display: block; height: 32px; @@ -988,13 +993,16 @@ const submit = () => { background: var(--el-color-primary-light-9); border-radius: 4px; } + .sc-cron:deep(.el-tabs__item.is-active) .sc-cron-num h4 { background: var(--el-color-primary); color: #fff; } + [data-theme='dark'] .sc-cron-num h4 { background: var(--el-color-white); } + .input-with-select .el-input-group__prepend { background-color: var(--el-fill-color-blank); } diff --git a/src/components/Cropper/src/CopperModal.vue b/src/components/Cropper/src/CopperModal.vue index 2365e5ec..c303b58c 100644 --- a/src/components/Cropper/src/CopperModal.vue +++ b/src/components/Cropper/src/CopperModal.vue @@ -2,26 +2,26 @@ <div> <Dialog v-model="dialogVisible" - :title="t('cropper.modalTitle')" - width="800px" - maxHeight="380px" :canFullscreen="false" + :title="t('cropper.modalTitle')" + maxHeight="380px" + width="800px" > <div :class="prefixCls"> <div :class="`${prefixCls}-left`"> <div :class="`${prefixCls}-cropper`"> <CropperImage v-if="src" + :circled="circled" :src="src" height="300px" - :circled="circled" @cropend="handleCropend" @ready="handleReady" /> </div> <div :class="`${prefixCls}-toolbar`"> - <el-upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload"> + <el-upload :beforeUpload="handleBeforeUpload" :fileList="[]" accept="image/*"> <el-tooltip :content="t('cropper.selectImage')" placement="bottom"> <XButton preIcon="ant-design:upload-outlined" type="primary" /> </el-tooltip> @@ -29,64 +29,64 @@ <el-space> <el-tooltip :content="t('cropper.btn_reset')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="ant-design:reload-outlined" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('reset')" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="ant-design:rotate-left-outlined" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('rotate', -45)" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="ant-design:rotate-right-outlined" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('rotate', 45)" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="vaadin:arrows-long-h" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('scaleX')" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="vaadin:arrows-long-v" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('scaleY')" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="ant-design:zoom-in-outlined" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('zoom', 0.1)" /> </el-tooltip> <el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom"> <XButton - type="primary" + :disabled="!src" preIcon="ant-design:zoom-out-outlined" size="small" - :disabled="!src" + type="primary" @click="handlerToolbar('zoom', -0.1)" /> </el-tooltip> @@ -95,14 +95,14 @@ </div> <div :class="`${prefixCls}-right`"> <div :class="`${prefixCls}-preview`"> - <img :src="previewSource" v-if="previewSource" :alt="t('cropper.preview')" /> + <img v-if="previewSource" :alt="t('cropper.preview')" :src="previewSource" /> </div> <template v-if="previewSource"> <div :class="`${prefixCls}-group`"> <el-avatar :src="previewSource" size="large" /> - <el-avatar :src="previewSource" :size="48" /> - <el-avatar :src="previewSource" :size="64" /> - <el-avatar :src="previewSource" :size="80" /> + <el-avatar :size="48" :src="previewSource" /> + <el-avatar :size="64" :src="previewSource" /> + <el-avatar :size="80" :src="previewSource" /> </div> </template> </div> @@ -113,7 +113,7 @@ </Dialog> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="CopperModal" setup> import { useDesign } from '@/hooks/web/useDesign' import { dataURLtoBlob } from '@/utils/filt' import { useI18n } from 'vue-i18n' @@ -173,12 +173,15 @@ async function handleOk() { const blob = dataURLtoBlob(previewSource.value) emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename }) } + function openModal() { dialogVisible.value = true } + function closeModal() { dialogVisible.value = false } + defineExpose({ openModal, closeModal }) </script> <style lang="scss"> diff --git a/src/components/Cropper/src/Cropper.vue b/src/components/Cropper/src/Cropper.vue index 459c97fa..ced43f96 100644 --- a/src/components/Cropper/src/Cropper.vue +++ b/src/components/Cropper/src/Cropper.vue @@ -3,14 +3,14 @@ <img v-show="isReady" ref="imgElRef" - :src="src" :alt="alt" :crossorigin="crossorigin" + :src="src" :style="getImageStyle" /> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="Cropper" setup> import { CSSProperties, PropType } from 'vue' import Cropper from 'cropperjs' import 'cropperjs/dist/cropper.css' diff --git a/src/components/Cropper/src/CropperAvatar.vue b/src/components/Cropper/src/CropperAvatar.vue index dc4c7475..179e0ec9 100644 --- a/src/components/Cropper/src/CropperAvatar.vue +++ b/src/components/Cropper/src/CropperAvatar.vue @@ -1,17 +1,17 @@ <template> <div class="user-info-head" @click="open()"> - <img :src="sourceValue" v-if="sourceValue" class="img-circle img-lg" alt="avatar" /> - <el-button :class="`${prefixCls}-upload-btn`" @click="open()" v-if="showBtn"> + <img v-if="sourceValue" :src="sourceValue" alt="avatar" class="img-circle img-lg" /> + <el-button v-if="showBtn" :class="`${prefixCls}-upload-btn`" @click="open()"> {{ btnText ? btnText : t('cropper.selectImage') }} </el-button> <CopperModal ref="cropperModelRef" - @upload-success="handleUploadSuccess" :srcValue="sourceValue" + @upload-success="handleUploadSuccess" /> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="CropperAvatar" setup> import { useDesign } from '@/hooks/web/useDesign' import { propTypes } from '@/utils/propTypes' @@ -54,9 +54,11 @@ function handleUploadSuccess({ source, data, filename }) { function open() { cropperModelRef.value.openModal() } + function close() { cropperModelRef.value.closeModal() } + defineExpose({ open, close @@ -104,17 +106,21 @@ $prefix-cls: #{$namespace}--cropper-avatar; margin: 10px auto; } } + .user-info-head { position: relative; display: inline-block; } + .img-circle { border-radius: 50%; } + .img-lg { width: 120px; height: 120px; } + .user-info-head:hover:after { content: '+'; position: absolute; diff --git a/src/components/Descriptions/src/Descriptions.vue b/src/components/Descriptions/src/Descriptions.vue index f1e77ddf..829c2014 100644 --- a/src/components/Descriptions/src/Descriptions.vue +++ b/src/components/Descriptions/src/Descriptions.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Descriptions" setup> import { PropType } from 'vue' import dayjs from 'dayjs' import { useDesign } from '@/hooks/web/useDesign' @@ -84,7 +84,7 @@ const toggleClick = () => { <div class="flex items-center"> {{ title }} <ElTooltip v-if="message" :content="message" placement="right"> - <Icon icon="ep:warning" class="ml-5px" /> + <Icon class="ml-5px" icon="ep:warning" /> </ElTooltip> </div> </div> @@ -95,8 +95,8 @@ const toggleClick = () => { <div v-show="show" :class="[`${prefixCls}-content`, 'p-10px']"> <ElDescriptions :column="props.columns" - border :direction="mobile ? 'vertical' : 'horizontal'" + border v-bind="getBindValue" > <template v-if="slots['extra']" #extra> @@ -114,8 +114,8 @@ const toggleClick = () => { :row="{ label: item.label }" - >{{ item.label }}</slot - > + >{{ item.label }} + </slot> </template> <template #default> diff --git a/src/components/Dialog/src/Dialog.vue b/src/components/Dialog/src/Dialog.vue index 48d5f1c3..449174d9 100644 --- a/src/components/Dialog/src/Dialog.vue +++ b/src/components/Dialog/src/Dialog.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Dialog" setup> import { propTypes } from '@/utils/propTypes' import { isNumber } from '@/utils/is' @@ -59,13 +59,13 @@ const dialogStyle = computed(() => { <template> <ElDialog - v-bind="getBindValue" - :fullscreen="isFullscreen" - destroy-on-close - lock-scroll - draggable - :width="width" :close-on-click-modal="true" + :fullscreen="isFullscreen" + :width="width" + destroy-on-close + draggable + lock-scroll + v-bind="getBindValue" > <template #header> <div class="flex justify-between"> @@ -74,8 +74,8 @@ const dialogStyle = computed(() => { </slot> <Icon v-if="fullscreen" - class="mr-22px cursor-pointer is-hover mt-2px z-10" :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'" + class="mr-22px cursor-pointer is-hover mt-2px z-10" color="var(--el-color-info)" @click="toggleFull" /> @@ -83,7 +83,7 @@ const dialogStyle = computed(() => { </template> <!-- 情况一:如果 scroll 为 true,说明开启滚动条 --> - <ElScrollbar :style="dialogStyle" v-if="scroll"> + <ElScrollbar v-if="scroll" :style="dialogStyle"> <slot></slot> </ElScrollbar> <!-- 情况二:如果 scroll 为 false,说明关闭滚动条滚动条 --> diff --git a/src/components/Echart/src/Echart.vue b/src/components/Echart/src/Echart.vue index 41fde039..31f2eea0 100644 --- a/src/components/Echart/src/Echart.vue +++ b/src/components/Echart/src/Echart.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="EChart" setup> import type { EChartsOption } from 'echarts' import echarts from '@/plugins/echarts' import { debounce } from 'lodash-es' diff --git a/src/components/Editor/src/Editor.vue b/src/components/Editor/src/Editor.vue index 4d8e7dde..092404e3 100644 --- a/src/components/Editor/src/Editor.vue +++ b/src/components/Editor/src/Editor.vue @@ -1,7 +1,7 @@ -<script setup lang="ts"> +<script lang="ts" name="Editor" setup> import { PropType } from 'vue' import { Editor, Toolbar } from '@wangeditor/editor-for-vue' -import { IDomEditor, IEditorConfig, i18nChangeLanguage } from '@wangeditor/editor' +import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor' import { propTypes } from '@/utils/propTypes' import { isNumber } from '@/utils/is' import { ElMessage } from 'element-plus' @@ -188,8 +188,8 @@ defineExpose({ <!-- 编辑器 --> <Editor v-model="valueHtml" - :editorId="editorId" :defaultConfig="editorConfig" + :editorId="editorId" :style="editorStyle" @on-change="handleChange" @on-created="handleCreated" diff --git a/src/components/Error/src/Error.vue b/src/components/Error/src/Error.vue index a979bc01..f8652a13 100644 --- a/src/components/Error/src/Error.vue +++ b/src/components/Error/src/Error.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Error" setup> import pageError from '@/assets/svgs/404.svg' import networkError from '@/assets/svgs/500.svg' import noPermission from '@/assets/svgs/403.svg' @@ -46,7 +46,7 @@ const btnClick = () => { <template> <div class="flex justify-center"> <div class="text-center"> - <img width="350" :src="errorMap[type].url" alt="" /> + <img :src="errorMap[type].url" alt="" width="350" /> <div class="text-14px text-[var(--el-color-info)]">{{ errorMap[type].message }}</div> <div class="mt-20px"> <ElButton type="primary" @click="btnClick">{{ errorMap[type].buttonText }}</ElButton> diff --git a/src/components/IFrame/src/IFrame.vue b/src/components/IFrame/src/IFrame.vue index 522da3cc..a8864a72 100644 --- a/src/components/IFrame/src/IFrame.vue +++ b/src/components/IFrame/src/IFrame.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="IFrame" setup> import { propTypes } from '@/utils/propTypes' const props = defineProps({ @@ -20,11 +20,11 @@ onMounted(() => { <template> <div v-loading="loading" :style="'height:' + height"> <iframe + ref="frameRef" :src="props.src" - style="width: 100%; height: 100%" frameborder="no" scrolling="auto" - ref="frameRef" + style="width: 100%; height: 100%" ></iframe> </div> </template> diff --git a/src/components/Icon/src/Icon.vue b/src/components/Icon/src/Icon.vue index bd94fcd4..92d791c2 100644 --- a/src/components/Icon/src/Icon.vue +++ b/src/components/Icon/src/Icon.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Icon" setup> import { propTypes } from '@/utils/propTypes' import Iconify from '@purge-icons/generated' import { useDesign } from '@/hooks/web/useDesign' @@ -72,7 +72,7 @@ watch( <template> <ElIcon :class="prefixCls" :color="color" :size="size"> - <svg v-if="isLocal" aria-hidden="true" :class="getSvgClass"> + <svg v-if="isLocal" :class="getSvgClass" aria-hidden="true"> <use :xlink:href="symbolId" /> </svg> diff --git a/src/components/Icon/src/IconSelect.vue b/src/components/Icon/src/IconSelect.vue index 1a124ca6..08fb1a2d 100644 --- a/src/components/Icon/src/IconSelect.vue +++ b/src/components/Icon/src/IconSelect.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="IconSelect" setup> import { CSSProperties } from 'vue' import { cloneDeep } from 'lodash-es' import { IconJson } from '@/components/Icon/src/data' @@ -116,13 +116,13 @@ watch( <ElInput v-model="inputValue" @click="visible = !visible"> <template #append> <ElPopover - :width="350" - trigger="click" - popper-class="pure-popper" :popper-options="{ placement: 'auto' }" :visible="visible" + :width="350" + popper-class="pure-popper" + trigger="click" > <template #reference> <div @@ -133,7 +133,7 @@ watch( </div> </template> - <ElInput class="p-2" v-model="filterValue" placeholder="搜索图标" clearable /> + <ElInput v-model="filterValue" class="p-2" clearable placeholder="搜索图标" /> <ElDivider border-style="dashed" /> <ElTabs v-model="currentActiveType" @tab-click="handleClick"> @@ -143,15 +143,15 @@ watch( :label="pane.label" :name="pane.name" > - <ElDivider class="tab-divider" border-style="dashed" /> + <ElDivider border-style="dashed" class="tab-divider" /> <ElScrollbar height="220px"> <ul class="flex flex-wrap px-2 ml-2"> <li v-for="(item, key) in pageList" :key="key" + :style="iconItemStyle(item)" :title="item" class="icon-item p-2 w-1/10 cursor-pointer mr-2 mt-1 flex justify-center items-center border border-solid" - :style="iconItemStyle(item)" @click="onChangeIcon(item)" > <Icon :icon="currentActiveType + item" /> @@ -163,13 +163,13 @@ watch( <ElDivider border-style="dashed" /> <ElPagination - small - :total="iconCount" - :page-size="pageSize" :current-page="currentPage" + :page-size="pageSize" + :total="iconCount" background - layout="prev, pager, next" class="flex items-center justify-center h-10" + layout="prev, pager, next" + small @current-change="onCurrentChange" /> </ElPopover> diff --git a/src/components/ImageViewer/src/ImageViewer.vue b/src/components/ImageViewer/src/ImageViewer.vue index a2ddc072..c416f566 100644 --- a/src/components/ImageViewer/src/ImageViewer.vue +++ b/src/components/ImageViewer/src/ImageViewer.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ImageViewer" setup> import { PropType } from 'vue' import { propTypes } from '@/utils/propTypes' diff --git a/src/components/Infotip/src/Infotip.vue b/src/components/Infotip/src/Infotip.vue index a03f34e2..dde5f4bc 100644 --- a/src/components/Infotip/src/Infotip.vue +++ b/src/components/Infotip/src/Infotip.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="InfoTip" setup> import { PropType } from 'vue' import { useDesign } from '@/hooks/web/useDesign' import { propTypes } from '@/utils/propTypes' @@ -34,14 +34,14 @@ const keyClick = (key: string) => { ]" > <div v-if="title" :class="[`${prefixCls}__header`, 'flex items-center']"> - <Icon icon="ep:warning-filled" :size="22" color="var(--el-color-primary)" /> + <Icon :size="22" color="var(--el-color-primary)" icon="ep:warning-filled" /> <span :class="[`${prefixCls}__title`, 'pl-5px text-16px font-bold']">{{ title }}</span> </div> <div :class="`${prefixCls}__content`"> <p v-for="(item, $index) in schema" :key="$index" class="text-14px mt-15px"> <Highlight - :keys="typeof item === 'string' ? [] : item.keys" :color="highlightColor" + :keys="typeof item === 'string' ? [] : item.keys" @click="keyClick" > {{ showIndex ? `${$index + 1}、` : '' }}{{ typeof item === 'string' ? item : item.label }} diff --git a/src/components/InputPassword/src/InputPassword.vue b/src/components/InputPassword/src/InputPassword.vue index 9e82cd41..19ce032c 100644 --- a/src/components/InputPassword/src/InputPassword.vue +++ b/src/components/InputPassword/src/InputPassword.vue @@ -1,8 +1,8 @@ -<script setup lang="ts"> +<script lang="ts" name="InputPassword" setup> import { propTypes } from '@/utils/propTypes' import { useConfigGlobal } from '@/hooks/web/useConfigGlobal' -import { zxcvbn } from '@zxcvbn-ts/core' import type { ZxcvbnResult } from '@zxcvbn-ts/core' +import { zxcvbn } from '@zxcvbn-ts/core' import { useDesign } from '@/hooks/web/useDesign' const { getPrefixCls } = useDesign() @@ -57,9 +57,9 @@ const getIconName = computed(() => (unref(textType) === 'password' ? 'ep:hide' : <template> <div :class="[prefixCls, `${prefixCls}--${configGlobal?.size}`]"> - <ElInput v-bind="$attrs" v-model="valueRef" :type="textType"> + <ElInput v-model="valueRef" :type="textType" v-bind="$attrs"> <template #suffix> - <Icon class="el-input__icon cursor-pointer" :icon="getIconName" @click="changeTextType" /> + <Icon :icon="getIconName" class="el-input__icon cursor-pointer" @click="changeTextType" /> </template> </ElInput> <div diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue index 788809a5..43112c55 100644 --- a/src/components/Pagination/index.vue +++ b/src/components/Pagination/index.vue @@ -2,19 +2,19 @@ <template> <el-pagination v-show="total > 0" - class="float-right mt-15px mb-15px" - :background="true" - layout="total, sizes, prev, pager, next, jumper" - :page-sizes="[10, 20, 30, 50, 100]" v-model:current-page="currentPage" v-model:page-size="pageSize" + :background="true" + :page-sizes="[10, 20, 30, 50, 100]" :pager-count="pagerCount" :total="total" + class="float-right mt-15px mb-15px" + layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </template> -<script setup> +<script name="Pagination" setup> import { computed } from 'vue' const props = defineProps({ diff --git a/src/components/Qrcode/src/Qrcode.vue b/src/components/Qrcode/src/Qrcode.vue index 0ef59ba7..2b72ef8b 100644 --- a/src/components/Qrcode/src/Qrcode.vue +++ b/src/components/Qrcode/src/Qrcode.vue @@ -1,7 +1,6 @@ -<script setup lang="ts"> -import { PropType, nextTick, ref, watch, computed, unref } from 'vue' -import QRCode from 'qrcode' -import { QRCodeRenderersOptions } from 'qrcode' +<script lang="ts" name="Qrcode" setup> +import { computed, nextTick, PropType, ref, unref, watch } from 'vue' +import QRCode, { QRCodeRenderersOptions } from 'qrcode' import { cloneDeep } from 'lodash-es' import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' @@ -230,7 +229,7 @@ const disabledClick = () => { @click="disabledClick" > <div class="absolute top-[50%] left-[50%] font-bold"> - <Icon icon="ep:refresh-right" :size="30" color="var(--el-color-primary)" /> + <Icon :size="30" color="var(--el-color-primary)" icon="ep:refresh-right" /> <div>{{ disabledText }}</div> </div> </div> diff --git a/src/components/Search/src/Search.vue b/src/components/Search/src/Search.vue index cb3d5dea..8309c43f 100644 --- a/src/components/Search/src/Search.vue +++ b/src/components/Search/src/Search.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Search" setup> import { PropType } from 'vue' import { propTypes } from '@/utils/propTypes' @@ -100,25 +100,25 @@ const setVisible = () => { <template> <!-- update by 芋艿:class="-mb-15px" 用于降低和 ContentWrap 组件的底部距离,避免空隙过大 --> <Form - :is-custom="false" - :label-width="labelWidth" - hide-required-asterisk :inline="inline" :is-col="isCol" + :is-custom="false" + :label-width="labelWidth" :schema="newSchema" - @register="register" class="-mb-15px" + hide-required-asterisk + @register="register" > <template #action> <div v-if="layout === 'inline'"> <!-- update by 芋艿:去除搜索的 type="primary",颜色变淡一点 --> <ElButton v-if="showSearch" @click="search"> - <Icon icon="ep:search" class="mr-5px" /> + <Icon class="mr-5px" icon="ep:search" /> {{ t('common.query') }} </ElButton> <!-- update by 芋艿:将 icon="ep:refresh-right" 修改成 icon="ep:refresh",和 ruoyi-vue 搜索保持一致 --> <ElButton v-if="showReset" @click="reset"> - <Icon icon="ep:refresh" class="mr-5px" /> + <Icon class="mr-5px" icon="ep:refresh" /> {{ t('common.reset') }} </ElButton> <ElButton v-if="expand" text @click="setVisible"> @@ -129,19 +129,19 @@ const setVisible = () => { <slot name="actionMore"></slot> </div> </template> - <template #[name] v-for="name in Object.keys($slots)" :key="name" - ><slot :name="name"></slot - ></template> + <template v-for="name in Object.keys($slots)" :key="name" #[name]> + <slot :name="name"></slot> + </template> </Form> <template v-if="layout === 'bottom'"> <div :style="bottonButtonStyle"> <ElButton v-if="showSearch" type="primary" @click="search"> - <Icon icon="ep:search" class="mr-5px" /> + <Icon class="mr-5px" icon="ep:search" /> {{ t('common.query') }} </ElButton> <ElButton v-if="showReset" @click="reset"> - <Icon icon="ep:refresh-right" class="mr-5px" /> + <Icon class="mr-5px" icon="ep:refresh-right" /> {{ t('common.reset') }} </ElButton> <ElButton v-if="expand" text @click="setVisible"> diff --git a/src/components/Sticky/src/Sticky.vue b/src/components/Sticky/src/Sticky.vue index 5d668059..bf9fc56b 100644 --- a/src/components/Sticky/src/Sticky.vue +++ b/src/components/Sticky/src/Sticky.vue @@ -1,7 +1,8 @@ -<script setup lang="ts"> +<script lang="ts" name="Sticky" setup> import { propTypes } from '@/utils/propTypes' import { isClient, useEventListener, useWindowSize } from '@vueuse/core' import type { CSSProperties } from 'vue' + const props = defineProps({ // 距离顶部或者底部的距离(单位px) offset: propTypes.number.def(0), @@ -120,7 +121,7 @@ const reset = () => { } </script> <template> - <div :style="{ height: height, zIndex: zIndex }" ref="refSticky"> + <div ref="refSticky" :style="{ height: height, zIndex: zIndex }"> <div :class="className" :style="{ diff --git a/src/components/Tooltip/src/Tooltip.vue b/src/components/Tooltip/src/Tooltip.vue index cad1cd29..eac37adb 100644 --- a/src/components/Tooltip/src/Tooltip.vue +++ b/src/components/Tooltip/src/Tooltip.vue @@ -1,5 +1,6 @@ -<script setup lang="ts"> +<script lang="ts" name="Tooltip" setup> import { propTypes } from '@/utils/propTypes' + defineProps({ titel: propTypes.string.def(''), message: propTypes.string.def(''), diff --git a/src/components/Verifition/src/Verify.vue b/src/components/Verifition/src/Verify.vue index 6bfc353e..861ed163 100644 --- a/src/components/Verifition/src/Verify.vue +++ b/src/components/Verifition/src/Verify.vue @@ -1,42 +1,42 @@ <template> - <div :class="mode == 'pop' ? 'mask' : ''" v-show="showBox"> + <div v-show="showBox" :class="mode == 'pop' ? 'mask' : ''"> <div :class="mode == 'pop' ? 'verifybox' : ''" :style="{ 'max-width': parseInt(imgSize.width) + 20 + 'px' }" > - <div class="verifybox-top" v-if="mode == 'pop'"> + <div v-if="mode == 'pop'" class="verifybox-top"> {{ t('captcha.verification') }} <span class="verifybox-close" @click="closeBox"> <i class="iconfont icon-close"></i> </span> </div> - <div class="verifybox-bottom" :style="{ padding: mode == 'pop' ? '10px' : '0' }"> + <div :style="{ padding: mode == 'pop' ? '10px' : '0' }" class="verifybox-bottom"> <!-- 验证码容器 --> <component - v-if="componentType" :is="componentType" - :captchaType="captchaType" - :type="verifyType" - :figure="figure" - :arith="arith" - :mode="mode" - :vSpace="vSpace" - :explain="explain" - :imgSize="imgSize" - :blockSize="blockSize" - :barSize="barSize" + v-if="componentType" ref="instance" + :arith="arith" + :barSize="barSize" + :blockSize="blockSize" + :captchaType="captchaType" + :explain="explain" + :figure="figure" + :imgSize="imgSize" + :mode="mode" + :type="verifyType" + :vSpace="vSpace" /> </div> </div> </div> </template> -<script type="text/babel"> +<script name="Verify" type="text/babel"> /** * Verify 验证码组件 * @description 分发验证码使用 * */ -import { VerifySlide, VerifyPoints } from './Verify' +import { VerifyPoints, VerifySlide } from './Verify' import { computed, ref, toRefs, watchEffect } from 'vue' export default { @@ -155,6 +155,7 @@ export default { border-radius: 5px; transform: translate(-50%, -50%); } + .verifybox-top { padding: 0 15px; height: 40px; @@ -165,10 +166,12 @@ export default { border-bottom: 1px solid #e4e7eb; box-sizing: border-box; } + .verifybox-bottom { padding: 10px; box-sizing: border-box; } + .verifybox-close { position: absolute; top: 13px; @@ -178,6 +181,7 @@ export default { text-align: center; cursor: pointer; } + .mask { position: fixed; top: 0; @@ -189,6 +193,7 @@ export default { /* display: none; */ transition: all 0.5s; } + .verify-tips { text-indent: 10px; position: absolute; @@ -199,22 +204,27 @@ export default { line-height: 30px; color: #fff; } + .suc-bg { background-color: rgba(92, 184, 92, 0.5); filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7f5CB85C, endcolorstr=#7f5CB85C); } + .err-bg { background-color: rgba(217, 83, 79, 0.5); filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7fD9534F, endcolorstr=#7fD9534F); } + .tips-enter, .tips-leave-to { bottom: -30px; } + .tips-enter-active, .tips-leave-active { transition: bottom 0.5s; } + /* ---------------------------- */ /*常规验证码*/ .verify-code { diff --git a/src/components/Verifition/src/Verify/VerifyPoints.vue b/src/components/Verifition/src/Verify/VerifyPoints.vue index 0e1fade7..5537c6e3 100644 --- a/src/components/Verifition/src/Verify/VerifyPoints.vue +++ b/src/components/Verifition/src/Verify/VerifyPoints.vue @@ -2,20 +2,20 @@ <div style="position: relative"> <div class="verify-img-out"> <div - class="verify-img-panel" :style="{ width: setSize.imgWidth, height: setSize.imgHeight, 'background-size': setSize.imgWidth + ' ' + setSize.imgHeight, 'margin-bottom': vSpace + 'px' }" + class="verify-img-panel" > - <div class="verify-refresh" style="z-index: 3" @click="refresh" v-show="showRefresh"> + <div v-show="showRefresh" class="verify-refresh" style="z-index: 3" @click="refresh"> <i class="iconfont icon-refresh"></i> </div> <img - :src="'data:image/png;base64,' + pointBackImgBase" ref="canvas" + :src="'data:image/png;base64,' + pointBackImgBase" alt="" style="width: 100%; height: 100%; display: block" @click="bindingClick ? canvasClick($event) : undefined" @@ -24,7 +24,6 @@ <div v-for="(tempPoint, index) in tempPoints" :key="index" - class="point-area" :style="{ 'background-color': '#1abd6c', color: '#fff', @@ -38,6 +37,7 @@ top: parseInt(tempPoint.y - 10) + 'px', left: parseInt(tempPoint.x - 10) + 'px' }" + class="point-area" > {{ index + 1 }} </div> @@ -45,19 +45,19 @@ </div> <!-- 'height': this.barSize.height, --> <div - class="verify-bar-area" :style="{ width: setSize.imgWidth, color: barAreaColor, 'border-color': barAreaBorderColor, 'line-height': barSize.height }" + class="verify-bar-area" > <span class="verify-msg">{{ text }}</span> </div> </div> </template> -<script type="text/babel" setup> +<script name="VerifyPoints" setup type="text/babel"> /** * VerifyPoints * @description 点选 @@ -65,7 +65,7 @@ import { resetSize } from './../utils/util' import { aesEncrypt } from './../utils/ase' import { getCode, reqCheck } from '@/api/login' -import { onMounted, reactive, ref, nextTick, toRefs, getCurrentInstance } from 'vue' +import { getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs } from 'vue' const props = defineProps({ //弹出式pop,固定fixed diff --git a/src/components/Verifition/src/Verify/VerifySlide.vue b/src/components/Verifition/src/Verify/VerifySlide.vue index 3961b129..68d8685d 100644 --- a/src/components/Verifition/src/Verify/VerifySlide.vue +++ b/src/components/Verifition/src/Verify/VerifySlide.vue @@ -2,20 +2,20 @@ <div style="position: relative"> <div v-if="type === '2'" - class="verify-img-out" :style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }" + class="verify-img-out" > - <div class="verify-img-panel" :style="{ width: setSize.imgWidth, height: setSize.imgHeight }"> + <div :style="{ width: setSize.imgWidth, height: setSize.imgHeight }" class="verify-img-panel"> <img :src="'data:image/png;base64,' + backImgBase" alt="" style="width: 100%; height: 100%; display: block" /> - <div class="verify-refresh" @click="refresh" v-show="showRefresh"> + <div v-show="showRefresh" class="verify-refresh" @click="refresh"> <i class="iconfont icon-refresh"></i> </div> <transition name="tips"> - <span class="verify-tips" v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'"> + <span v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'" class="verify-tips"> {{ tipWords }} </span> </transition> @@ -23,24 +23,21 @@ </div> <!-- 公共部分 --> <div - class="verify-bar-area" :style="{ width: setSize.imgWidth, height: barSize.height, 'line-height': barSize.height }" + class="verify-bar-area" > <span class="verify-msg" v-text="text"></span> <div - class="verify-left-bar" :style="{ width: leftBarWidth !== undefined ? leftBarWidth : barSize.height, height: barSize.height, 'border-color': leftBarBorderColor, transaction: transitionWidth }" + class="verify-left-bar" > <span class="verify-msg" v-text="finishText"></span> <div - class="verify-move-block" - @touchstart="start" - @mousedown="start" :style="{ width: barSize.height, height: barSize.height, @@ -48,17 +45,20 @@ left: moveBlockLeft, transition: transitionLeft }" + class="verify-move-block" + @mousedown="start" + @touchstart="start" > <i :class="['verify-icon iconfont', iconClass]" :style="{ color: iconColor }"></i> <div v-if="type === '2'" - class="verify-sub-block" :style="{ width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px', height: setSize.imgHeight, top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px', 'background-size': setSize.imgWidth + ' ' + setSize.imgHeight }" + class="verify-sub-block" > <img :src="'data:image/png;base64,' + blockBackImgBase" @@ -71,7 +71,7 @@ </div> </div> </template> -<script type="text/babel" setup> +<script name="VerifySlide" setup type="text/babel"> /** * VerifySlide * @description 滑块 diff --git a/src/components/XButton/src/XButton.vue b/src/components/XButton/src/XButton.vue index 3ef71230..e68dff24 100644 --- a/src/components/XButton/src/XButton.vue +++ b/src/components/XButton/src/XButton.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="XButton" setup> import { PropType } from 'vue' import { propTypes } from '@/utils/propTypes' @@ -30,9 +30,9 @@ const getBindValue = computed(() => { <template> <el-button v-bind="getBindValue" @click="onClick"> - <Icon :icon="preIcon" v-if="preIcon" class="mr-1px" /> + <Icon v-if="preIcon" :icon="preIcon" class="mr-1px" /> {{ title ? title : '' }} - <Icon :icon="postIcon" v-if="postIcon" class="mr-1px" /> + <Icon v-if="postIcon" :icon="postIcon" class="mr-1px" /> </el-button> </template> <style lang="scss" scoped> @@ -40,6 +40,7 @@ const getBindValue = computed(() => { margin-left: 0; padding: 8px 4px; } + :deep(.el-button.is-link) { margin-left: 0; padding: 8px 4px; diff --git a/src/components/XButton/src/XTextButton.vue b/src/components/XButton/src/XTextButton.vue index a256a985..c2ff9796 100644 --- a/src/components/XButton/src/XTextButton.vue +++ b/src/components/XButton/src/XTextButton.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="XTextButton" setup> import { propTypes } from '@/utils/propTypes' import { PropType } from 'vue' @@ -29,9 +29,9 @@ const getBindValue = computed(() => { <template> <el-button link v-bind="getBindValue" @click="onClick"> - <Icon :icon="preIcon" v-if="preIcon" class="mr-1px" /> + <Icon v-if="preIcon" :icon="preIcon" class="mr-1px" /> {{ title ? title : '' }} - <Icon :icon="postIcon" v-if="postIcon" class="mr-1px" /> + <Icon v-if="postIcon" :icon="postIcon" class="mr-1px" /> </el-button> </template> <style lang="scss" scoped> @@ -39,6 +39,7 @@ const getBindValue = computed(() => { margin-left: 0; padding: 8px 4px; } + :deep(.el-button.is-link) { margin-left: 0; padding: 8px 4px; diff --git a/src/layout/components/AppView.vue b/src/layout/components/AppView.vue index dda59ed1..bf35ebe3 100644 --- a/src/layout/components/AppView.vue +++ b/src/layout/components/AppView.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="AppView" setup> import { useTagsViewStore } from '@/store/modules/tagsView' import { useAppStore } from '@/store/modules/app' import { Footer } from '@/layout/components/Footer' diff --git a/src/layout/components/Collapse/src/Collapse.vue b/src/layout/components/Collapse/src/Collapse.vue index a8f47dc6..523c34d4 100644 --- a/src/layout/components/Collapse/src/Collapse.vue +++ b/src/layout/components/Collapse/src/Collapse.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Collapse" setup> import { useAppStore } from '@/store/modules/app' import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' @@ -24,9 +24,9 @@ const toggleCollapse = () => { <template> <div :class="prefixCls"> <Icon - :size="18" - :icon="collapse ? 'ep:expand' : 'ep:fold'" :color="color" + :icon="collapse ? 'ep:expand' : 'ep:fold'" + :size="18" class="cursor-pointer" @click="toggleCollapse" /> diff --git a/src/layout/components/ContextMenu/src/ContextMenu.vue b/src/layout/components/ContextMenu/src/ContextMenu.vue index 8c18f2a1..de819692 100644 --- a/src/layout/components/ContextMenu/src/ContextMenu.vue +++ b/src/layout/components/ContextMenu/src/ContextMenu.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ContextMenu" setup> import { PropType } from 'vue' import { useDesign } from '@/hooks/web/useDesign' @@ -51,9 +51,9 @@ defineExpose({ :class="prefixCls" :trigger="trigger" placement="bottom-start" + popper-class="v-context-menu-popper" @command="command" @visible-change="visibleChange" - popper-class="v-context-menu-popper" > <slot></slot> <template #dropdown> @@ -61,11 +61,12 @@ defineExpose({ <ElDropdownItem v-for="(item, index) in schema" :key="`dropdown${index}`" - :divided="item.divided" - :disabled="item.disabled" :command="item" + :disabled="item.disabled" + :divided="item.divided" > - <Icon :icon="item.icon" /> {{ t(item.label) }} + <Icon :icon="item.icon" /> + {{ t(item.label) }} </ElDropdownItem> </ElDropdownMenu> </template> diff --git a/src/layout/components/Footer/src/Footer.vue b/src/layout/components/Footer/src/Footer.vue index 239812c6..c9fcd896 100644 --- a/src/layout/components/Footer/src/Footer.vue +++ b/src/layout/components/Footer/src/Footer.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Footer" setup> import { useAppStore } from '@/store/modules/app' import { useDesign } from '@/hooks/web/useDesign' diff --git a/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue b/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue index 0e56724b..d16fbb2a 100644 --- a/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue +++ b/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="LocaleDropdown" setup> import { useLocaleStore } from '@/store/modules/locale' import { useLocale } from '@/hooks/web/useLocale' import { propTypes } from '@/utils/propTypes' @@ -33,11 +33,11 @@ const setLang = (lang: LocaleType) => { <template> <ElDropdown :class="prefixCls" trigger="click" @command="setLang"> <Icon - :size="18" - icon="ion:language-sharp" - class="cursor-pointer" :class="$attrs.class" :color="color" + :size="18" + class="cursor-pointer" + icon="ion:language-sharp" /> <template #dropdown> <ElDropdownMenu> diff --git a/src/layout/components/Logo/src/Logo.vue b/src/layout/components/Logo/src/Logo.vue index 9b70a0dc..17bdf1af 100644 --- a/src/layout/components/Logo/src/Logo.vue +++ b/src/layout/components/Logo/src/Logo.vue @@ -1,5 +1,5 @@ -<script setup lang="ts"> -import { ref, watch, computed, onMounted, unref } from 'vue' +<script lang="ts" name="Logo" setup> +import { computed, onMounted, ref, unref, watch } from 'vue' import { useAppStore } from '@/store/modules/app' import { useDesign } from '@/hooks/web/useDesign' @@ -66,8 +66,8 @@ watch( to="/" > <img - src="@/assets/imgs/logo.png" class="w-[calc(var(--logo-height)-10px)] h-[calc(var(--logo-height)-10px)]" + src="@/assets/imgs/logo.png" /> <div v-if="show" diff --git a/src/layout/components/Message/src/Message.vue b/src/layout/components/Message/src/Message.vue index d968eb6f..444e4611 100644 --- a/src/layout/components/Message/src/Message.vue +++ b/src/layout/components/Message/src/Message.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="Message" setup> import { formatDate } from '@/utils/formatTime' import * as NotifyMessageApi from '@/api/system/notify/message' @@ -40,10 +40,10 @@ onMounted(() => { </script> <template> <div class="message"> - <ElPopover placement="bottom" :width="400" trigger="click"> + <ElPopover :width="400" placement="bottom" trigger="click"> <template #reference> <ElBadge :is-dot="unreadCount > 0" class="item"> - <Icon icon="ep:bell" :size="18" class="cursor-pointer" @click="getList" /> + <Icon :size="18" class="cursor-pointer" icon="ep:bell" @click="getList" /> </ElBadge> </template> <ElTabs v-model="activeName"> @@ -51,7 +51,7 @@ onMounted(() => { <div class="message-list"> <template v-for="item in list" :key="item.id"> <div class="message-item"> - <img src="@/assets/imgs/avatar.gif" alt="" class="message-icon" /> + <img alt="" class="message-icon" src="@/assets/imgs/avatar.gif" /> <div class="message-content"> <span class="message-title"> {{ item.templateNickname }}:{{ item.templateContent }} @@ -67,12 +67,12 @@ onMounted(() => { </ElTabs> <!-- 更多 --> <div style="text-align: right; margin-top: 10px"> - <XButton type="primary" preIcon="ep:view" title="查看全部" @click="goMyList" /> + <XButton preIcon="ep:view" title="查看全部" type="primary" @click="goMyList" /> </div> </ElPopover> </div> </template> -<style scoped lang="scss"> +<style lang="scss" scoped> .message-empty { display: flex; flex-direction: column; @@ -81,28 +81,35 @@ onMounted(() => { height: 260px; line-height: 45px; } + .message-list { display: flex; flex-direction: column; + .message-item { display: flex; align-items: center; padding: 20px 0; border-bottom: 1px solid var(--el-border-color-light); + &:last-child { border: none; } + .message-icon { width: 40px; height: 40px; margin: 0 20px 0 5px; } + .message-content { display: flex; flex-direction: column; + .message-title { margin-bottom: 5px; } + .message-date { font-size: 12px; color: var(--el-text-color-secondary); diff --git a/src/layout/components/Screenfull/src/Screenfull.vue b/src/layout/components/Screenfull/src/Screenfull.vue index 32a12e73..d0c4c44c 100644 --- a/src/layout/components/Screenfull/src/Screenfull.vue +++ b/src/layout/components/Screenfull/src/Screenfull.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ScreenFull" setup> import { Icon } from '@/components/Icon' import { useFullscreen } from '@vueuse/core' import { propTypes } from '@/utils/propTypes' @@ -22,9 +22,9 @@ const toggleFullscreen = () => { <template> <div :class="prefixCls" @click="toggleFullscreen"> <Icon - :size="18" - :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'" :color="color" + :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'" + :size="18" /> </div> </template> diff --git a/src/layout/components/Setting/src/Setting.vue b/src/layout/components/Setting/src/Setting.vue index de0532fd..8a395a81 100644 --- a/src/layout/components/Setting/src/Setting.vue +++ b/src/layout/components/Setting/src/Setting.vue @@ -1,12 +1,12 @@ -<script setup lang="ts"> +<script lang="ts" name="Setting" setup> import { ElMessage } from 'element-plus' -import { useCssVar, useClipboard } from '@vueuse/core' +import { useClipboard, useCssVar } from '@vueuse/core' import { CACHE_KEY, useCache } from '@/hooks/web/useCache' import { useDesign } from '@/hooks/web/useDesign' -import { trim, setCssVar } from '@/utils' -import { colorIsDark, lighten, hexToRGB } from '@/utils/color' +import { setCssVar, trim } from '@/utils' +import { colorIsDark, hexToRGB, lighten } from '@/utils/color' import { useAppStore } from '@/store/modules/app' import { ThemeSwitch } from '@/layout/components/ThemeSwitch' import ColorRadioPicker from './components/ColorRadioPicker.vue' @@ -202,10 +202,10 @@ const clear = () => { class="fixed top-[45%] right-0 w-40px h-40px text-center leading-40px bg-[var(--el-color-primary)] cursor-pointer" @click="drawer = true" > - <Icon icon="ep:setting" color="#fff" /> + <Icon color="#fff" icon="ep:setting" /> </div> - <ElDrawer v-model="drawer" direction="rtl" size="350px" :z-index="4000"> + <ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px"> <template #header> <span class="text-16px font-700">{{ t('setting.projectSetting') }}</span> </template> @@ -279,10 +279,10 @@ const clear = () => { <ElDivider /> <div> - <ElButton type="primary" class="w-full" @click="copyConfig">{{ t('setting.copy') }}</ElButton> + <ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton> </div> <div class="mt-5px"> - <ElButton type="danger" class="w-full" @click="clear"> + <ElButton class="w-full" type="danger" @click="clear"> {{ t('setting.clearAndReset') }} </ElButton> </div> diff --git a/src/layout/components/Setting/src/components/ColorRadioPicker.vue b/src/layout/components/Setting/src/components/ColorRadioPicker.vue index 7c5e2404..8ef0f8c0 100644 --- a/src/layout/components/Setting/src/components/ColorRadioPicker.vue +++ b/src/layout/components/Setting/src/components/ColorRadioPicker.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ColorRadioPicker" setup> import { PropType } from 'vue' import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' @@ -42,14 +42,14 @@ watch( <span v-for="(item, i) in schema" :key="`radio-${i}`" - class="w-20px h-20px cursor-pointer rounded-2px border-solid border-gray-300 border-2px text-center leading-20px mb-5px" :class="{ 'is-active': colorVal === item }" :style="{ background: item }" + class="w-20px h-20px cursor-pointer rounded-2px border-solid border-gray-300 border-2px text-center leading-20px mb-5px" @click="colorVal = item" > - <Icon v-if="colorVal === item" color="#fff" icon="ep:check" :size="16" /> + <Icon v-if="colorVal === item" :size="16" color="#fff" icon="ep:check" /> </span> </div> </template> diff --git a/src/layout/components/Setting/src/components/InterfaceDisplay.vue b/src/layout/components/Setting/src/components/InterfaceDisplay.vue index e0dc0885..12f6fbc0 100644 --- a/src/layout/components/Setting/src/components/InterfaceDisplay.vue +++ b/src/layout/components/Setting/src/components/InterfaceDisplay.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="InterfaceDisplay" setup> import { setCssVar } from '@/utils' import { useDesign } from '@/hooks/web/useDesign' diff --git a/src/layout/components/Setting/src/components/LayoutRadioPicker.vue b/src/layout/components/Setting/src/components/LayoutRadioPicker.vue index 07dbab95..b500683a 100644 --- a/src/layout/components/Setting/src/components/LayoutRadioPicker.vue +++ b/src/layout/components/Setting/src/components/LayoutRadioPicker.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="LayoutRadioPicker" setup> import { useAppStore } from '@/store/modules/app' import { useDesign } from '@/hooks/web/useDesign' diff --git a/src/layout/components/SizeDropdown/src/SizeDropdown.vue b/src/layout/components/SizeDropdown/src/SizeDropdown.vue index 0dc698c0..d191dbe2 100644 --- a/src/layout/components/SizeDropdown/src/SizeDropdown.vue +++ b/src/layout/components/SizeDropdown/src/SizeDropdown.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="SizeDropdown" setup> import { useAppStore } from '@/store/modules/app' import { propTypes } from '@/utils/propTypes' @@ -26,7 +26,7 @@ const setCurrentSize = (size: ElementPlusSize) => { <template> <ElDropdown :class="prefixCls" trigger="click" @command="setCurrentSize"> - <Icon :size="18" icon="mdi:format-size" :color="color" class="cursor-pointer" /> + <Icon :color="color" :size="18" class="cursor-pointer" icon="mdi:format-size" /> <template #dropdown> <ElDropdownMenu> <ElDropdownItem v-for="item in sizeMap" :key="item" :command="item"> diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue index d6e9768d..6b4f7be7 100644 --- a/src/layout/components/TagsView/src/TagsView.vue +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="TagsView" setup> import type { RouteLocationNormalizedLoaded, RouterLinkProps } from 'vue-router' import { usePermissionStore } from '@/store/modules/permission' import { useTagsViewStore } from '@/store/modules/tagsView' @@ -266,15 +266,24 @@ watch( @click="move(-200)" > <Icon - icon="ep:d-arrow-left" :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'" + icon="ep:d-arrow-left" /> </span> <div class="overflow-hidden flex-1"> <ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll"> <div class="flex h-full"> <ContextMenu + v-for="item in visitedViews" + :key="item.fullPath" :ref="itemRefs.set" + :class="[ + `${prefixCls}__item`, + item?.meta?.affix ? `${prefixCls}__item--affix` : '', + { + 'is-active': isActive(item) + } + ]" :schema="[ { icon: 'ep:refresh', @@ -332,23 +341,14 @@ watch( } } ]" - v-for="item in visitedViews" - :key="item.fullPath" :tag-item="item" - :class="[ - `${prefixCls}__item`, - item?.meta?.affix ? `${prefixCls}__item--affix` : '', - { - 'is-active': isActive(item) - } - ]" @visible-change="visibleChange" > <div> - <router-link :ref="tagLinksRefs.set" :to="{ ...item }" custom v-slot="{ navigate }"> + <router-link :ref="tagLinksRefs.set" v-slot="{ navigate }" :to="{ ...item }" custom> <div - @click="navigate" class="h-full flex justify-center items-center whitespace-nowrap pl-15px" + @click="navigate" > <Icon v-if=" @@ -364,9 +364,9 @@ watch( {{ t(item?.meta?.title as string) }} <Icon :class="`${prefixCls}__item--close`" + :size="12" color="#333" icon="ep:close" - :size="12" @click.prevent.stop="closeSelectedTag(item)" /> </div> @@ -382,8 +382,8 @@ watch( @click="move(200)" > <Icon - icon="ep:d-arrow-right" :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'" + icon="ep:d-arrow-right" /> </span> <span @@ -392,12 +392,11 @@ watch( @click="refreshSelectedTag(selectedTag)" > <Icon - icon="ep:refresh-right" :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'" + icon="ep:refresh-right" /> </span> <ContextMenu - trigger="click" :schema="[ { icon: 'ep:refresh', @@ -449,14 +448,15 @@ watch( } } ]" + trigger="click" > <span :class="`${prefixCls}__tool`" class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer block" > <Icon - icon="ep:menu" :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'" + icon="ep:menu" /> </span> </ContextMenu> @@ -513,6 +513,7 @@ $prefix-cls: #{$namespace}-tags-view; display: none; transform: translate(0, -50%); } + &:not(.#{$prefix-cls}__item--affix):hover { .#{$prefix-cls}__item--close { display: block; @@ -530,6 +531,7 @@ $prefix-cls: #{$namespace}-tags-view; color: var(--el-color-white); background-color: var(--el-color-primary); border: 1px solid var(--el-color-primary); + .#{$prefix-cls}__item--close { :deep(span) { color: var(--el-color-white) !important; @@ -573,6 +575,7 @@ $prefix-cls: #{$namespace}-tags-view; &__item.is-active { color: var(--el-color-white); background-color: var(--el-color-primary); + .#{$prefix-cls}__item--close { :deep(span) { color: var(--el-color-white) !important; diff --git a/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue b/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue index 45243011..5a926508 100644 --- a/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue +++ b/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="ThemeSwitch" setup> import { useAppStore } from '@/store/modules/app' import { useIcon } from '@/hooks/web/useIcon' import { useDesign } from '@/hooks/web/useDesign' @@ -26,14 +26,14 @@ const themeChange = (val: boolean) => { <template> <ElSwitch - :class="prefixCls" v-model="isDark" - inline-prompt - :border-color="blackColor" - :inactive-color="blackColor" :active-color="blackColor" :active-icon="Sun" + :border-color="blackColor" + :class="prefixCls" + :inactive-color="blackColor" :inactive-icon="CrescentMoon" + inline-prompt @change="themeChange" /> </template> diff --git a/src/layout/components/UserInfo/src/UserInfo.vue b/src/layout/components/UserInfo/src/UserInfo.vue index 7ccadb57..20837540 100644 --- a/src/layout/components/UserInfo/src/UserInfo.vue +++ b/src/layout/components/UserInfo/src/UserInfo.vue @@ -1,4 +1,4 @@ -<script setup lang="ts"> +<script lang="ts" name="UserInfo" setup> import { ElMessageBox } from 'element-plus' import { CACHE_KEY, useCache } from '@/hooks/web/useCache' diff --git a/src/views/Error/403.vue b/src/views/Error/403.vue index d477304b..cb106465 100644 --- a/src/views/Error/403.vue +++ b/src/views/Error/403.vue @@ -1,6 +1,6 @@ <template> <Error type="403" @error-click="push('/')" /> </template> -<script setup lang="ts"> +<script lang="ts" name="Error403" setup> const { push } = useRouter() </script> diff --git a/src/views/Error/404.vue b/src/views/Error/404.vue index d1ccb62e..c55d3325 100644 --- a/src/views/Error/404.vue +++ b/src/views/Error/404.vue @@ -1,6 +1,6 @@ <template> <Error @error-click="push('/')" /> </template> -<script setup lang="ts"> +<script lang="ts" name="Error404" setup> const { push } = useRouter() </script> diff --git a/src/views/Error/500.vue b/src/views/Error/500.vue index 9f784fd2..6cfe47b7 100644 --- a/src/views/Error/500.vue +++ b/src/views/Error/500.vue @@ -1,6 +1,6 @@ <template> <Error type="500" @error-click="push('/')" /> </template> -<script setup lang="ts"> +<script lang="ts" name="Error500" setup> const { push } = useRouter() </script> diff --git a/src/views/Home/Index2.vue b/src/views/Home/Index2.vue index 0f588510..457aced3 100644 --- a/src/views/Home/Index2.vue +++ b/src/views/Home/Index2.vue @@ -1,26 +1,26 @@ <template> - <el-row :gutter="20" justify="space-between" :class="prefixCls"> - <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> - <el-card shadow="hover" class="mb-20px"> - <el-skeleton :loading="loading" animated :rows="2"> + <el-row :class="prefixCls" :gutter="20" justify="space-between"> + <el-col :lg="6" :md="12" :sm="12" :xl="6" :xs="24"> + <el-card class="mb-20px" shadow="hover"> + <el-skeleton :loading="loading" :rows="2" animated> <template #default> <div :class="`${prefixCls}__item flex justify-between`"> <div> <div :class="`${prefixCls}__item--icon ${prefixCls}__item--peoples p-16px inline-block rounded-6px`" > - <Icon icon="svg-icon:peoples" :size="40" /> + <Icon :size="40" icon="svg-icon:peoples" /> </div> </div> <div class="flex flex-col justify-between"> - <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{ - t('analysis.newUser') - }}</div> + <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`" + >{{ t('analysis.newUser') }} + </div> <CountTo - class="text-20px font-700 text-right" - :start-val="0" - :end-val="102400" :duration="2600" + :end-val="102400" + :start-val="0" + class="text-20px font-700 text-right" /> </div> </div> @@ -29,27 +29,27 @@ </el-card> </el-col> - <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> - <el-card shadow="hover" class="mb-20px"> - <el-skeleton :loading="loading" animated :rows="2"> + <el-col :lg="6" :md="12" :sm="12" :xl="6" :xs="24"> + <el-card class="mb-20px" shadow="hover"> + <el-skeleton :loading="loading" :rows="2" animated> <template #default> <div :class="`${prefixCls}__item flex justify-between`"> <div> <div :class="`${prefixCls}__item--icon ${prefixCls}__item--message p-16px inline-block rounded-6px`" > - <Icon icon="svg-icon:message" :size="40" /> + <Icon :size="40" icon="svg-icon:message" /> </div> </div> <div class="flex flex-col justify-between"> - <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{ - t('analysis.unreadInformation') - }}</div> + <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`" + >{{ t('analysis.unreadInformation') }} + </div> <CountTo - class="text-20px font-700 text-right" - :start-val="0" - :end-val="81212" :duration="2600" + :end-val="81212" + :start-val="0" + class="text-20px font-700 text-right" /> </div> </div> @@ -58,27 +58,27 @@ </el-card> </el-col> - <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> - <el-card shadow="hover" class="mb-20px"> - <el-skeleton :loading="loading" animated :rows="2"> + <el-col :lg="6" :md="12" :sm="12" :xl="6" :xs="24"> + <el-card class="mb-20px" shadow="hover"> + <el-skeleton :loading="loading" :rows="2" animated> <template #default> <div :class="`${prefixCls}__item flex justify-between`"> <div> <div :class="`${prefixCls}__item--icon ${prefixCls}__item--money p-16px inline-block rounded-6px`" > - <Icon icon="svg-icon:money" :size="40" /> + <Icon :size="40" icon="svg-icon:money" /> </div> </div> <div class="flex flex-col justify-between"> - <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{ - t('analysis.transactionAmount') - }}</div> + <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`" + >{{ t('analysis.transactionAmount') }} + </div> <CountTo - class="text-20px font-700 text-right" - :start-val="0" - :end-val="9280" :duration="2600" + :end-val="9280" + :start-val="0" + class="text-20px font-700 text-right" /> </div> </div> @@ -87,27 +87,27 @@ </el-card> </el-col> - <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> - <el-card shadow="hover" class="mb-20px"> - <el-skeleton :loading="loading" animated :rows="2"> + <el-col :lg="6" :md="12" :sm="12" :xl="6" :xs="24"> + <el-card class="mb-20px" shadow="hover"> + <el-skeleton :loading="loading" :rows="2" animated> <template #default> <div :class="`${prefixCls}__item flex justify-between`"> <div> <div :class="`${prefixCls}__item--icon ${prefixCls}__item--shopping p-16px inline-block rounded-6px`" > - <Icon icon="svg-icon:shopping" :size="40" /> + <Icon :size="40" icon="svg-icon:shopping" /> </div> </div> <div class="flex flex-col justify-between"> - <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{ - t('analysis.totalShopping') - }}</div> + <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`" + >{{ t('analysis.totalShopping') }} + </div> <CountTo - class="text-20px font-700 text-right" - :start-val="0" - :end-val="13600" :duration="2600" + :end-val="13600" + :start-val="0" + class="text-20px font-700 text-right" /> </div> </div> @@ -117,36 +117,36 @@ </el-col> </el-row> <el-row :gutter="20" justify="space-between"> - <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24"> - <el-card shadow="hover" class="mb-20px"> + <el-col :lg="10" :md="24" :sm="24" :xl="10" :xs="24"> + <el-card class="mb-20px" shadow="hover"> <el-skeleton :loading="loading" animated> - <Echart :options="pieOptionsData" :height="300" /> + <Echart :height="300" :options="pieOptionsData" /> </el-skeleton> </el-card> </el-col> - <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24"> - <el-card shadow="hover" class="mb-20px"> + <el-col :lg="14" :md="24" :sm="24" :xl="14" :xs="24"> + <el-card class="mb-20px" shadow="hover"> <el-skeleton :loading="loading" animated> - <Echart :options="barOptionsData" :height="300" /> + <Echart :height="300" :options="barOptionsData" /> </el-skeleton> </el-card> </el-col> <el-col :span="24"> - <el-card shadow="hover" class="mb-20px"> - <el-skeleton :loading="loading" animated :rows="4"> - <Echart :options="lineOptionsData" :height="350" /> + <el-card class="mb-20px" shadow="hover"> + <el-skeleton :loading="loading" :rows="4" animated> + <Echart :height="350" :options="lineOptionsData" /> </el-skeleton> </el-card> </el-col> </el-row> </template> -<script setup lang="ts"> +<script lang="ts" name="Home2" setup> import { set } from 'lodash-es' import { EChartsOption } from 'echarts' import { useDesign } from '@/hooks/web/useDesign' import type { AnalysisTotalTypes } from './types' -import { pieOptions, barOptions, lineOptions } from './echarts-data' +import { barOptions, lineOptions, pieOptions } from './echarts-data' const { t } = useI18n() const loading = ref(true) @@ -291,18 +291,23 @@ $prefix-cls: #{$namespace}-panel; :deep(.#{$namespace}-icon) { color: #fff !important; } + .#{$prefix-cls}__item--icon { transition: all 0.38s ease-out; } + .#{$prefix-cls}__item--peoples { background: #40c9c6; } + .#{$prefix-cls}__item--message { background: #36a3f7; } + .#{$prefix-cls}__item--money { background: #f4516c; } + .#{$prefix-cls}__item--shopping { background: #34bfa3; } diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue index a0186ab7..eb323d86 100644 --- a/src/views/Login/Login.vue +++ b/src/views/Login/Login.vue @@ -60,7 +60,7 @@ </div> </div> </template> -<script lang="ts" setup> +<script lang="ts" name="Login" setup> import { underlineToHump } from '@/utils' import { useDesign } from '@/hooks/web/useDesign' diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue index 176aba3b..8f0b8b64 100644 --- a/src/views/Login/components/LoginForm.vue +++ b/src/views/Login/components/LoginForm.vue @@ -1,13 +1,13 @@ <template> <el-form - :model="loginData.loginForm" - :rules="LoginRules" - label-position="top" - class="login-form" - label-width="120px" - size="large" v-show="getShow" ref="formLogin" + :model="loginData.loginForm" + :rules="LoginRules" + class="login-form" + label-position="top" + label-width="120px" + size="large" > <el-row style="maring-left: -10px; maring-right: -10px"> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> @@ -16,12 +16,12 @@ </el-form-item> </el-col> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> - <el-form-item prop="tenantName" v-if="loginData.tenantEnable === 'true'"> + <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName"> <el-input - type="text" v-model="loginData.loginForm.tenantName" :placeholder="t('login.tenantNamePlaceholder')" :prefix-icon="iconHouse" + type="text" /> </el-form-item> </el-col> @@ -38,11 +38,11 @@ <el-form-item prop="password"> <el-input v-model="loginData.loginForm.password" - type="password" :placeholder="t('login.passwordPlaceholder')" - show-password - @keyup.enter="getCode()" :prefix-icon="iconLock" + show-password + type="password" + @keyup.enter="getCode()" /> </el-form-item> </el-col> @@ -57,8 +57,8 @@ {{ t('login.remember') }} </el-checkbox> </el-col> - <el-col :span="12" :offset="6"> - <el-link type="primary" style="float: right">{{ t('login.forgetPassword') }}</el-link> + <el-col :offset="6" :span="12"> + <el-link style="float: right" type="primary">{{ t('login.forgetPassword') }}</el-link> </el-col> </el-row> </el-form-item> @@ -67,41 +67,41 @@ <el-form-item> <XButton :loading="loginLoading" - type="primary" - class="w-[100%]" :title="t('login.login')" + class="w-[100%]" + type="primary" @click="getCode()" /> </el-form-item> </el-col> <Verify ref="verify" - mode="pop" :captchaType="captchaType" :imgSize="{ width: '400px', height: '200px' }" + mode="pop" @success="handleLogin" /> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> <el-form-item> - <el-row justify="space-between" style="width: 100%" :gutter="5"> + <el-row :gutter="5" justify="space-between" style="width: 100%"> <el-col :span="8"> <XButton - class="w-[100%]" :title="t('login.btnMobile')" + class="w-[100%]" @click="setLoginState(LoginStateEnum.MOBILE)" /> </el-col> <el-col :span="8"> <XButton - class="w-[100%]" :title="t('login.btnQRCode')" + class="w-[100%]" @click="setLoginState(LoginStateEnum.QR_CODE)" /> </el-col> <el-col :span="8"> <XButton - class="w-[100%]" :title="t('login.btnRegister')" + class="w-[100%]" @click="setLoginState(LoginStateEnum.REGISTER)" /> </el-col> @@ -127,7 +127,7 @@ </el-row> </el-form> </template> -<script setup lang="ts"> +<script lang="ts" name="LoginForm" setup> import { ElLoading } from 'element-plus' import LoginFormTitle from './LoginFormTitle.vue' import type { RouteLocationNormalizedLoaded } from 'vue-router' diff --git a/src/views/Login/components/LoginFormTitle.vue b/src/views/Login/components/LoginFormTitle.vue index ea55be93..b192a5fa 100644 --- a/src/views/Login/components/LoginFormTitle.vue +++ b/src/views/Login/components/LoginFormTitle.vue @@ -3,7 +3,7 @@ {{ getFormTitle }} </h2> </template> -<script setup lang="ts"> +<script lang="ts" name="LoginFormTitle" setup> import { LoginStateEnum, useLoginState } from './useLogin' const { t } = useI18n() diff --git a/src/views/Login/components/MobileForm.vue b/src/views/Login/components/MobileForm.vue index 3a0ab686..4c291f9e 100644 --- a/src/views/Login/components/MobileForm.vue +++ b/src/views/Login/components/MobileForm.vue @@ -1,13 +1,13 @@ <template> <el-form - :model="loginData.loginForm" - :rules="rules" - label-position="top" - class="login-form" - label-width="120px" - size="large" v-show="getShow" ref="formSmsLogin" + :model="loginData.loginForm" + :rules="rules" + class="login-form" + label-position="top" + label-width="120px" + size="large" > <el-row style="margin-left: -10px; margin-right: -10px"> <!-- 租户名 --> @@ -17,12 +17,12 @@ </el-form-item> </el-col> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> - <el-form-item prop="tenantName" v-if="loginData.tenantEnable === 'true'"> + <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName"> <el-input - type="text" v-model="loginData.loginForm.tenantName" :placeholder="t('login.tenantNamePlaceholder')" :prefix-icon="iconHouse" + type="text" /> </el-form-item> </el-col> @@ -39,7 +39,7 @@ <!-- 验证码 --> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> <el-form-item prop="code"> - <el-row justify="space-between" style="width: 100%" :gutter="5"> + <el-row :gutter="5" justify="space-between" style="width: 100%"> <el-col :span="24"> <el-input v-model="loginData.loginForm.code" @@ -50,9 +50,9 @@ <template #append> <span v-if="mobileCodeTimer <= 0" - @click="getSmsCode" class="getMobileCode" style="cursor: pointer" + @click="getSmsCode" > {{ t('login.getSmsCode') }} </span> @@ -71,9 +71,9 @@ <el-form-item> <XButton :loading="loginLoading" - type="primary" - class="w-[100%]" :title="t('login.login')" + class="w-[100%]" + type="primary" @click="signIn()" /> </el-form-item> @@ -82,8 +82,8 @@ <el-form-item> <XButton :loading="loginLoading" - class="w-[100%]" :title="t('login.backLogin')" + class="w-[100%]" @click="handleBackLogin()" /> </el-form-item> @@ -91,7 +91,7 @@ </el-row> </el-form> </template> -<script setup lang="ts"> +<script lang="ts" name="MobileForm" setup> import type { RouteLocationNormalizedLoaded } from 'vue-router' import { useIcon } from '@/hooks/web/useIcon' @@ -100,7 +100,7 @@ import { setTenantId, setToken } from '@/utils/auth' import { usePermissionStore } from '@/store/modules/permission' import { getTenantIdByName, sendSmsCode, smsLogin } from '@/api/login' import LoginFormTitle from './LoginFormTitle.vue' -import { useLoginState, LoginStateEnum, useFormValid } from './useLogin' +import { LoginStateEnum, useFormValid, useLoginState } from './useLogin' const { t } = useI18n() const message = useMessage() diff --git a/src/views/Login/components/QrCodeForm.vue b/src/views/Login/components/QrCodeForm.vue index bdf7e2a5..c485d287 100644 --- a/src/views/Login/components/QrCodeForm.vue +++ b/src/views/Login/components/QrCodeForm.vue @@ -4,23 +4,23 @@ <LoginFormTitle style="width: 100%" /> </el-col> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> - <el-card shadow="hover" class="mb-10px text-center"> + <el-card class="mb-10px text-center" shadow="hover"> <Qrcode :logo="logoImg" /> </el-card> </el-col> <el-divider class="enter-x">{{ t('login.qrcode') }}</el-divider> <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> <div class="w-[100%] mt-15px"> - <XButton class="w-[100%]" :title="t('login.backLogin')" @click="handleBackLogin()" /> + <XButton :title="t('login.backLogin')" class="w-[100%]" @click="handleBackLogin()" /> </div> </el-col> </el-row> </template> -<script setup lang="ts"> +<script lang="ts" name="QrCodeForm" setup> import logoImg from '@/assets/imgs/logo.png' import LoginFormTitle from './LoginFormTitle.vue' -import { useLoginState, LoginStateEnum } from './useLogin' +import { LoginStateEnum, useLoginState } from './useLogin' const { t } = useI18n() const { handleBackLogin, getLoginState } = useLoginState() diff --git a/src/views/Login/components/RegisterForm.vue b/src/views/Login/components/RegisterForm.vue index 7d048506..de6b5967 100644 --- a/src/views/Login/components/RegisterForm.vue +++ b/src/views/Login/components/RegisterForm.vue @@ -1,12 +1,12 @@ <template> <Form - :schema="schema" - :rules="rules" - label-position="top" - hide-required-asterisk - size="large" v-show="getShow" + :rules="rules" + :schema="schema" class="dark:(border-1 border-[var(--el-border-color)] border-solid)" + hide-required-asterisk + label-position="top" + size="large" @register="register" > <template #title> @@ -23,25 +23,25 @@ <div class="w-[100%]"> <XButton :loading="loading" - type="primary" - class="w-[100%]" :title="t('login.register')" + class="w-[100%]" + type="primary" @click="loginRegister()" /> </div> <div class="w-[100%] mt-15px"> - <XButton class="w-[100%]" :title="t('login.hasUser')" @click="handleBackLogin()" /> + <XButton :title="t('login.hasUser')" class="w-[100%]" @click="handleBackLogin()" /> </div> </template> </Form> </template> -<script setup lang="ts"> +<script lang="ts" name="RegisterForm" setup> import type { FormRules } from 'element-plus' import { useForm } from '@/hooks/web/useForm' import { useValidator } from '@/hooks/web/useValidator' import LoginFormTitle from './LoginFormTitle.vue' -import { useLoginState, LoginStateEnum } from './useLogin' +import { LoginStateEnum, useLoginState } from './useLogin' import { FormSchema } from '@/types/form' const { t } = useI18n() diff --git a/src/views/Profile/components/BasicInfo.vue b/src/views/Profile/components/BasicInfo.vue index f5e9da72..f3cc81c7 100644 --- a/src/views/Profile/components/BasicInfo.vue +++ b/src/views/Profile/components/BasicInfo.vue @@ -1,5 +1,5 @@ <template> - <Form ref="formRef" :rules="rules" :schema="schema" :labelWidth="80"> + <Form ref="formRef" :labelWidth="80" :rules="rules" :schema="schema"> <template #sex="form"> <el-radio-group v-model="form['sex']"> <el-radio :label="1">{{ t('profile.user.man') }}</el-radio> @@ -8,9 +8,9 @@ </template> </Form> <XButton :title="t('common.save')" @click="submit()" /> - <XButton type="danger" :title="t('common.reset')" @click="init()" /> + <XButton :title="t('common.reset')" type="danger" @click="init()" /> </template> -<script setup lang="ts"> +<script lang="ts" name="BasicInfo" setup> import type { FormRules } from 'element-plus' import { ElMessage } from 'element-plus' diff --git a/src/views/Profile/components/ProfileUser.vue b/src/views/Profile/components/ProfileUser.vue index 8657bc75..523985d4 100644 --- a/src/views/Profile/components/ProfileUser.vue +++ b/src/views/Profile/components/ProfileUser.vue @@ -5,41 +5,48 @@ </div> <ul class="list-group list-group-striped"> <li class="list-group-item"> - <Icon icon="ep:user" class="mr-5px" />{{ t('profile.user.username') }} + <Icon class="mr-5px" icon="ep:user" /> + {{ t('profile.user.username') }} <div class="pull-right">{{ userInfo?.username }}</div> </li> <li class="list-group-item"> - <Icon icon="ep:phone" class="mr-5px" />{{ t('profile.user.mobile') }} + <Icon class="mr-5px" icon="ep:phone" /> + {{ t('profile.user.mobile') }} <div class="pull-right">{{ userInfo?.mobile }}</div> </li> <li class="list-group-item"> - <Icon icon="fontisto:email" class="mr-5px" />{{ t('profile.user.email') }} + <Icon class="mr-5px" icon="fontisto:email" /> + {{ t('profile.user.email') }} <div class="pull-right">{{ userInfo?.email }}</div> </li> <li class="list-group-item"> - <Icon icon="carbon:tree-view-alt" class="mr-5px" />{{ t('profile.user.dept') }} - <div class="pull-right" v-if="userInfo?.dept">{{ userInfo?.dept.name }}</div> + <Icon class="mr-5px" icon="carbon:tree-view-alt" /> + {{ t('profile.user.dept') }} + <div v-if="userInfo?.dept" class="pull-right">{{ userInfo?.dept.name }}</div> </li> <li class="list-group-item"> - <Icon icon="ep:suitcase" class="mr-5px" />{{ t('profile.user.posts') }} - <div class="pull-right" v-if="userInfo?.posts"> + <Icon class="mr-5px" icon="ep:suitcase" /> + {{ t('profile.user.posts') }} + <div v-if="userInfo?.posts" class="pull-right"> {{ userInfo?.posts.map((post) => post.name).join(',') }} </div> </li> <li class="list-group-item"> - <Icon icon="icon-park-outline:peoples" class="mr-5px" />{{ t('profile.user.roles') }} - <div class="pull-right" v-if="userInfo?.roles"> + <Icon class="mr-5px" icon="icon-park-outline:peoples" /> + {{ t('profile.user.roles') }} + <div v-if="userInfo?.roles" class="pull-right"> {{ userInfo?.roles.map((role) => role.name).join(',') }} </div> </li> <li class="list-group-item"> - <Icon icon="ep:calendar" class="mr-5px" />{{ t('profile.user.createTime') }} + <Icon class="mr-5px" icon="ep:calendar" /> + {{ t('profile.user.createTime') }} <div class="pull-right">{{ formatDate(userInfo?.createTime) }}</div> </li> </ul> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="ProfileUser" setup> import { formatDate } from '@/utils/formatTime' import UserAvatar from './UserAvatar.vue' @@ -62,6 +69,7 @@ onMounted(async () => { position: relative; height: 120px; } + .list-group-striped > .list-group-item { border-left: 0; border-right: 0; @@ -82,6 +90,7 @@ onMounted(async () => { padding: 11px 0px; font-size: 13px; } + .pull-right { float: right !important; } diff --git a/src/views/Profile/components/ResetPwd.vue b/src/views/Profile/components/ResetPwd.vue index 0d6f9cc4..d348511e 100644 --- a/src/views/Profile/components/ResetPwd.vue +++ b/src/views/Profile/components/ResetPwd.vue @@ -10,13 +10,13 @@ <InputPassword v-model="password.confirmPassword" strength /> </el-form-item> <el-form-item> - <XButton type="primary" @click="submit(formRef)" :title="t('common.save')" /> - <XButton type="danger" :title="t('common.reset')" @click="reset(formRef)" /> + <XButton :title="t('common.save')" type="primary" @click="submit(formRef)" /> + <XButton :title="t('common.reset')" type="danger" @click="reset(formRef)" /> </el-form-item> </el-form> </template> -<script setup lang="ts"> -import type { FormRules, FormInstance } from 'element-plus' +<script lang="ts" name="ResetPwd" setup> +import type { FormInstance, FormRules } from 'element-plus' import { InputPassword } from '@/components/InputPassword' import { updateUserPassword } from '@/api/system/user/profile' diff --git a/src/views/Profile/components/UserAvatar.vue b/src/views/Profile/components/UserAvatar.vue index 50a14d81..88dc8d9e 100644 --- a/src/views/Profile/components/UserAvatar.vue +++ b/src/views/Profile/components/UserAvatar.vue @@ -2,17 +2,18 @@ <div class="change-avatar"> <CropperAvatar ref="cropperRef" - :value="avatar" - :showBtn="false" - @change="handelUpload" :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" + :showBtn="false" + :value="avatar" width="120px" + @change="handelUpload" /> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="UserAvatar" setup> import { propTypes } from '@/utils/propTypes' import { uploadAvatar } from '@/api/system/user/profile' + const props = defineProps({ img: propTypes.string.def('') }) @@ -27,7 +28,7 @@ const handelUpload = async ({ data }) => { } </script> -<style scoped lang="scss"> +<style lang="scss" scoped> .change-avatar { img { display: block; diff --git a/src/views/bpm/form/editor/index.vue b/src/views/bpm/form/editor/index.vue index 3a28697f..14a2c50f 100644 --- a/src/views/bpm/form/editor/index.vue +++ b/src/views/bpm/form/editor/index.vue @@ -4,14 +4,15 @@ <fc-designer ref="designer" height="780px"> <template #handle> <el-button round size="small" type="primary" @click="handleSave"> - <Icon icon="ep:plus" class="mr-5px" /> 保存 + <Icon class="mr-5px" icon="ep:plus" /> + 保存 </el-button> </template> </fc-designer> </ContentWrap> <!-- 表单保存的弹窗 --> - <Dialog title="保存表单" v-model="dialogVisible" width="600"> + <Dialog v-model="dialogVisible" title="保存表单" width="600"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px"> <el-form-item label="表单名" prop="name"> <el-input v-model="formData.name" placeholder="请输入表单名" /> @@ -28,16 +29,16 @@ </el-radio-group> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" /> + <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmFormEditor" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as FormApi from '@/api/bpm/form' diff --git a/src/views/bpm/group/UserGroupForm.vue b/src/views/bpm/group/UserGroupForm.vue index e8011d8c..1adbea15 100644 --- a/src/views/bpm/group/UserGroupForm.vue +++ b/src/views/bpm/group/UserGroupForm.vue @@ -1,17 +1,17 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px" - v-loading="formLoading" > <el-form-item label="组名" prop="name"> <el-input v-model="formData.name" placeholder="请输入组名" /> </el-form-item> <el-form-item label="描述"> - <el-input type="textarea" v-model="formData.name" placeholder="请输入描述" /> + <el-input v-model="formData.name" placeholder="请输入描述" type="textarea" /> </el-form-item> <el-form-item label="成员" prop="memberUserIds"> <el-select v-model="formData.memberUserIds" multiple placeholder="请选择成员"> @@ -36,12 +36,12 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="UserGroupForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as UserGroupApi from '@/api/bpm/userGroup' diff --git a/src/views/bpm/model/ModelForm.vue b/src/views/bpm/model/ModelForm.vue index 24484ec6..1967e17f 100644 --- a/src/views/bpm/model/ModelForm.vue +++ b/src/views/bpm/model/ModelForm.vue @@ -1,45 +1,45 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible" width="600"> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="600"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="110px" - v-loading="formLoading" > <el-form-item label="流程标识" prop="key"> <el-input v-model="formData.key" + :disabled="!!formData.id" placeholder="请输入流标标识" style="width: 330px" - :disabled="!!formData.id" /> <el-tooltip v-if="!formData.id" class="item" - effect="light" content="新建后,流程标识不可修改!" + effect="light" placement="top" > - <i style="padding-left: 5px" class="el-icon-question"></i> + <i class="el-icon-question" style="padding-left: 5px"></i> </el-tooltip> - <el-tooltip v-else class="item" effect="light" content="流程标识不可修改!" placement="top"> - <i style="padding-left: 5px" class="el-icon-question"></i> + <el-tooltip v-else class="item" content="流程标识不可修改!" effect="light" placement="top"> + <i class="el-icon-question" style="padding-left: 5px"></i> </el-tooltip> </el-form-item> <el-form-item label="流程名称" prop="name"> <el-input v-model="formData.name" - placeholder="请输入流程名称" :disabled="!!formData.id" clearable + placeholder="请输入流程名称" /> </el-form-item> <el-form-item v-if="formData.id" label="流程分类" prop="category"> <el-select v-model="formData.category" - placeholder="请选择流程分类" clearable + placeholder="请选择流程分类" style="width: 100%" > <el-option @@ -51,7 +51,7 @@ </el-select> </el-form-item> <el-form-item label="流程描述" prop="description"> - <el-input type="textarea" v-model="formData.description" clearable /> + <el-input v-model="formData.description" clearable type="textarea" /> </el-form-item> <div v-if="formData.id"> <el-form-item label="表单类型" prop="formType"> @@ -87,11 +87,11 @@ /> <el-tooltip class="item" - effect="light" content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create" + effect="light" placement="top" > - <i style="padding-left: 5px" class="el-icon-question"></i> + <i class="el-icon-question" style="padding-left: 5px"></i> </el-tooltip> </el-form-item> <el-form-item @@ -106,26 +106,27 @@ /> <el-tooltip class="item" - effect="light" content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view" + effect="light" placement="top" > - <i style="padding-left: 5px" class="el-icon-question"></i> + <i class="el-icon-question" style="padding-left: 5px"></i> </el-tooltip> </el-form-item> </div> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ModelForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { ElMessageBox } from 'element-plus' import * as ModelApi from '@/api/bpm/model' import * as FormApi from '@/api/bpm/form' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/bpm/model/ModelImportForm.vue b/src/views/bpm/model/ModelImportForm.vue index 76493c95..ad2d0b66 100644 --- a/src/views/bpm/model/ModelImportForm.vue +++ b/src/views/bpm/model/ModelImportForm.vue @@ -1,24 +1,24 @@ <template> - <Dialog title="导入流程" v-model="dialogVisible" width="400"> + <Dialog v-model="dialogVisible" title="导入流程" width="400"> <div> <el-upload ref="uploadRef" - :action="importUrl" - :headers="uploadHeaders" - :data="formData" - name="bpmnFile" v-model:file-list="fileList" - drag + :action="importUrl" :auto-upload="false" - accept=".bpmn, .xml" + :data="formData" + :disabled="formLoading" + :headers="uploadHeaders" :limit="1" + :on-error="submitFormError" :on-exceed="handleExceed" :on-success="submitFormSuccess" - :on-error="submitFormError" - :disabled="formLoading" + accept=".bpmn, .xml" + drag + name="bpmnFile" > <Icon class="el-icon--upload" icon="ep:upload-filled" /> - <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> + <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em></div> <template #tip> <div class="el-upload__tip" style="color: red"> 提示:仅允许导入“bpm”或“xml”格式文件! @@ -33,10 +33,10 @@ /> </el-form-item> <el-form-item label="流程名称" prop="name"> - <el-input v-model="formData.name" placeholder="请输入流程名称" clearable /> + <el-input v-model="formData.name" clearable placeholder="请输入流程名称" /> </el-form-item> <el-form-item label="流程描述" prop="description"> - <el-input type="textarea" v-model="formData.description" clearable /> + <el-input v-model="formData.description" clearable type="textarea" /> </el-form-item> </el-form> </div> @@ -44,13 +44,14 @@ </el-upload> </div> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ModelImportForm" setup> import { getAccessToken, getTenantId } from '@/utils/auth' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/bpm/oa/leave/create.vue b/src/views/bpm/oa/leave/create.vue index 321ec609..6bf7760e 100644 --- a/src/views/bpm/oa/leave/create.vue +++ b/src/views/bpm/oa/leave/create.vue @@ -1,14 +1,14 @@ <template> - <Dialog title="发起 OA 请假流程" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="发起 OA 请假流程"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="请假类型" prop="type"> - <el-select v-model="formData.type" placeholder="请选择请假类型" clearable> + <el-select v-model="formData.type" clearable placeholder="请选择请假类型"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)" :key="dict.value" @@ -19,35 +19,36 @@ </el-form-item> <el-form-item label="开始时间" prop="startTime"> <el-date-picker - clearable v-model="formData.startTime" + clearable + placeholder="请选择开始时间" type="datetime" value-format="x" - placeholder="请选择开始时间" /> </el-form-item> <el-form-item label="结束时间" prop="endTime"> <el-date-picker - clearable v-model="formData.endTime" + clearable + placeholder="请选择结束时间" type="datetime" value-format="x" - placeholder="请选择结束时间" /> </el-form-item> <el-form-item label="原因" prop="reason"> - <el-input v-model="formData.reason" type="textarea" placeholder="请输请假原因" /> + <el-input v-model="formData.reason" placeholder="请输请假原因" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmOALeaveCreate" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as LeaveApi from '@/api/bpm/leave' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/bpm/oa/leave/detail.vue b/src/views/bpm/oa/leave/detail.vue index 838be149..caf07f50 100644 --- a/src/views/bpm/oa/leave/detail.vue +++ b/src/views/bpm/oa/leave/detail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="200"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="200" :scroll="true" title="详情"> + <el-descriptions :column="1" border> <el-descriptions-item label="请假类型"> <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="detailData.type" /> </el-descriptions-item> @@ -16,7 +16,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmOALeaveDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as LeaveApi from '@/api/bpm/leave' diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue b/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue index 3a3e244b..684a9495 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue @@ -1,20 +1,20 @@ <template> - <el-card class="box-card" v-loading="loading"> + <el-card v-loading="loading" class="box-card"> <template #header> <span class="el-icon-picture-outline">流程图</span> </template> <my-process-viewer key="designer" - :value="bpmnXml" - v-bind="bpmnControlForm" - :prefix="bpmnControlForm.prefix" :activityData="activityList" + :prefix="bpmnControlForm.prefix" :processInstanceData="processInstance" :taskData="tasks" + :value="bpmnXml" + v-bind="bpmnControlForm" /> </el-card> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmProcessInstanceBpmnViewer" setup> import { propTypes } from '@/utils/propTypes' import * as ActivityApi from '@/api/bpm/activity' // import * as DefinitionApi from '@/api/bpm/definition' diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue index a8aa0120..dbb90753 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue @@ -1,9 +1,9 @@ <template> - <el-card class="box-card" v-loading="loading"> + <el-card v-loading="loading" class="box-card"> <template #header> <span class="el-icon-picture-outline">审批记录</span> </template> - <el-col :span="16" :offset="4"> + <el-col :offset="4" :span="16"> <div class="block"> <el-timeline> <el-timeline-item @@ -16,9 +16,9 @@ <el-card :body-style="{ padding: '10px' }"> <label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px"> 审批人:{{ item.assigneeUser.nickname }} - <el-tag type="info" size="small">{{ item.assigneeUser.deptName }}</el-tag> + <el-tag size="small" type="info">{{ item.assigneeUser.deptName }}</el-tag> </label> - <label style="font-weight: normal" v-if="item.createTime">创建时间:</label> + <label v-if="item.createTime" style="font-weight: normal">创建时间:</label> <label style="color: #8a909c; font-weight: normal"> {{ formatDate(item?.createTime) }} </label> @@ -44,7 +44,7 @@ </el-col> </el-card> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmProcessInstanceTaskList" setup> import { formatDate, formatPast2 } from '@/utils/formatTime' import { propTypes } from '@/utils/propTypes' diff --git a/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue b/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue index 0f16deeb..1c9971cd 100644 --- a/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue +++ b/src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog title="转派审批人" v-model="dialogVisible" width="500"> + <Dialog v-model="dialogVisible" title="转派审批人" width="500"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="110px" - v-loading="formLoading" > <el-form-item label="新审批人" prop="assigneeUserId"> <el-select v-model="formData.assigneeUserId" clearable style="width: 100%"> @@ -19,12 +19,12 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmTaskUpdateAssigneeForm" setup> import * as TaskApi from '@/api/bpm/task' import * as UserApi from '@/api/system/user' diff --git a/src/views/bpm/task/done/TaskDetail.vue b/src/views/bpm/task/done/TaskDetail.vue index 4c293c17..68624d19 100644 --- a/src/views/bpm/task/done/TaskDetail.vue +++ b/src/views/bpm/task/done/TaskDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情"> + <el-descriptions :column="1" border> <el-descriptions-item label="任务编号" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -25,7 +25,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmTaskDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as TaskApi from '@/api/bpm/task' diff --git a/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue b/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue index 2ddebab1..b1140a60 100644 --- a/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue +++ b/src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog title="修改任务规则" v-model="dialogVisible" width="600"> + <Dialog v-model="dialogVisible" title="修改任务规则" width="600"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px"> <el-form-item label="任务名称" prop="taskDefinitionName"> - <el-input v-model="formData.taskDefinitionName" placeholder="请输入流标标识" disabled /> + <el-input v-model="formData.taskDefinitionName" disabled placeholder="请输入流标标识" /> </el-form-item> <el-form-item label="任务标识" prop="taskDefinitionKey"> - <el-input v-model="formData.taskDefinitionKey" placeholder="请输入任务标识" disabled /> + <el-input v-model="formData.taskDefinitionKey" disabled placeholder="请输入任务标识" /> </el-form-item> <el-form-item label="规则类型" prop="type"> <el-select v-model="formData.type" clearable style="width: 100%"> @@ -18,7 +18,7 @@ </el-select> </el-form-item> <el-form-item v-if="formData.type === 10" label="指定角色" prop="roleIds"> - <el-select v-model="formData.roleIds" multiple clearable style="width: 100%"> + <el-select v-model="formData.roleIds" clearable multiple style="width: 100%"> <el-option v-for="item in roleOptions" :key="item.id" @@ -28,24 +28,24 @@ </el-select> </el-form-item> <el-form-item + v-if="formData.type === 20 || formData.type === 21" label="指定部门" prop="deptIds" span="24" - v-if="formData.type === 20 || formData.type === 21" > <el-tree-select ref="treeRef" v-model="formData.deptIds" - node-key="id" - show-checkbox - :props="defaultProps" :data="deptTreeOptions" + :props="defaultProps" empty-text="加载中,请稍后" multiple + node-key="id" + show-checkbox /> </el-form-item> - <el-form-item label="指定岗位" prop="postIds" span="24" v-if="formData.type === 22"> - <el-select v-model="formData.postIds" multiple clearable style="width: 100%"> + <el-form-item v-if="formData.type === 22" label="指定岗位" prop="postIds" span="24"> + <el-select v-model="formData.postIds" clearable multiple style="width: 100%"> <el-option v-for="item in postOptions" :key="parseInt(item.id)" @@ -55,12 +55,12 @@ </el-select> </el-form-item> <el-form-item + v-if="formData.type === 30 || formData.type === 31 || formData.type === 32" label="指定用户" prop="userIds" span="24" - v-if="formData.type === 30 || formData.type === 31 || formData.type === 32" > - <el-select v-model="formData.userIds" multiple clearable style="width: 100%"> + <el-select v-model="formData.userIds" clearable multiple style="width: 100%"> <el-option v-for="item in userOptions" :key="parseInt(item.id)" @@ -69,8 +69,8 @@ /> </el-select> </el-form-item> - <el-form-item label="指定用户组" prop="userGroupIds" v-if="formData.type === 40"> - <el-select v-model="formData.userGroupIds" multiple clearable style="width: 100%"> + <el-form-item v-if="formData.type === 40" label="指定用户组" prop="userGroupIds"> + <el-select v-model="formData.userGroupIds" clearable multiple style="width: 100%"> <el-option v-for="item in userGroupOptions" :key="parseInt(item.id)" @@ -79,8 +79,8 @@ /> </el-select> </el-form-item> - <el-form-item label="指定脚本" prop="scripts" v-if="formData.type === 50"> - <el-select v-model="formData.scripts" multiple clearable style="width: 100%"> + <el-form-item v-if="formData.type === 50" label="指定脚本" prop="scripts"> + <el-select v-model="formData.scripts" clearable multiple style="width: 100%"> <el-option v-for="dict in taskAssignScriptDictDatas" :key="dict.value" @@ -92,20 +92,21 @@ </el-form> <!-- 操作按钮 --> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="BpmTaskAssignRuleForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { handleTree, defaultProps } from '@/utils/tree' +import { defaultProps, handleTree } from '@/utils/tree' import * as TaskAssignRuleApi from '@/api/bpm/taskAssignRule' import * as RoleApi from '@/api/system/role' import * as DeptApi from '@/api/system/dept' import * as PostApi from '@/api/system/post' import * as UserApi from '@/api/system/user' import * as UserGroupApi from '@/api/bpm/userGroup' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue index 4746b0c7..fac82aa3 100644 --- a/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue +++ b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情" width="800"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志主键" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -33,14 +33,14 @@ <el-descriptions-item label="操作结果"> <div v-if="detailData.resultCode === 0">正常</div> <div v-else-if="detailData.resultCode > 0" - >失败 | {{ detailData.resultCode }} | {{ detailData.resultMsg }}</div - > + >失败 | {{ detailData.resultCode }} | {{ detailData.resultMsg }} + </div> </el-descriptions-item> </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ApiAccessLogDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as ApiAccessLog from '@/api/infra/apiAccessLog' diff --git a/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue index 4b279924..7fe17570 100644 --- a/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue +++ b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情" width="800"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志主键" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -32,12 +32,12 @@ <el-descriptions-item label="异常名"> {{ detailData.exceptionName }} </el-descriptions-item> - <el-descriptions-item label="异常堆栈" v-if="detailData.exceptionStackTrace"> + <el-descriptions-item v-if="detailData.exceptionStackTrace" label="异常堆栈"> <el-input - type="textarea" - :readonly="true" - :autosize="{ maxRows: 20 }" v-model="detailData.exceptionStackTrace" + :autosize="{ maxRows: 20 }" + :readonly="true" + type="textarea" /> </el-descriptions-item> <el-descriptions-item label="处理状态"> @@ -46,16 +46,16 @@ :value="detailData.processStatus" /> </el-descriptions-item> - <el-descriptions-item label="处理人" v-if="detailData.processUserId"> + <el-descriptions-item v-if="detailData.processUserId" label="处理人"> {{ detailData.processUserId }} </el-descriptions-item> - <el-descriptions-item label="处理时间" v-if="detailData.processTime"> + <el-descriptions-item v-if="detailData.processTime" label="处理时间"> {{ formatDate(detailData.processTime) }} </el-descriptions-item> </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ApiErrorLogDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as ApiErrorLog from '@/api/infra/apiErrorLog' diff --git a/src/views/infra/codegen/EditTable.vue b/src/views/infra/codegen/EditTable.vue index 8d9f498e..e540f96b 100644 --- a/src/views/infra/codegen/EditTable.vue +++ b/src/views/infra/codegen/EditTable.vue @@ -13,16 +13,17 @@ </el-tabs> <el-form> <el-form-item style="float: right"> - <el-button type="primary" @click="submitForm" :loading="formLoading">保存</el-button> + <el-button :loading="formLoading" type="primary" @click="submitForm">保存</el-button> <el-button @click="close">返回</el-button> </el-form-item> </el-form> </ContentWrap> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraCodegenEditTable" setup> import { useTagsViewStore } from '@/store/modules/tagsView' import { BasicInfoForm, ColumInfoForm, GenerateInfoForm } from './components' import * as CodegenApi from '@/api/infra/codegen' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const { push, currentRoute } = useRouter() // 路由 diff --git a/src/views/infra/codegen/ImportTable.vue b/src/views/infra/codegen/ImportTable.vue index 0146b6c3..fb37aa26 100644 --- a/src/views/infra/codegen/ImportTable.vue +++ b/src/views/infra/codegen/ImportTable.vue @@ -1,12 +1,12 @@ <template> - <Dialog title="导入表" v-model="dialogVisible" width="800px"> + <Dialog v-model="dialogVisible" title="导入表" width="800px"> <!-- 搜索栏 --> - <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> + <el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="68px"> <el-form-item label="数据源" prop="dataSourceConfigId"> <el-select v-model="queryParams.dataSourceConfigId" - placeholder="请选择数据源" class="!w-240px" + placeholder="请选择数据源" > <el-option v-for="config in dataSourceConfigList" @@ -19,54 +19,61 @@ <el-form-item label="表名称" prop="name"> <el-input v-model="queryParams.name" - placeholder="请输入表名称" - clearable - @keyup.enter="getList" class="!w-240px" + clearable + placeholder="请输入表名称" + @keyup.enter="getList" /> </el-form-item> <el-form-item label="表描述" prop="comment"> <el-input v-model="queryParams.comment" - placeholder="请输入表描述" - clearable - @keyup.enter="getList" class="!w-240px" + clearable + placeholder="请输入表描述" + @keyup.enter="getList" /> </el-form-item> <el-form-item> - <el-button @click="getList"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button @click="getList"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 + </el-button> </el-form-item> </el-form> <!-- 列表 --> <el-row> <el-table - v-loading="dbTableLoading" - @row-click="handleRowClick" ref="tableRef" + v-loading="dbTableLoading" :data="dbTableList" - @selection-change="handleSelectionChange" height="260px" + @row-click="handleRowClick" + @selection-change="handleSelectionChange" > <el-table-column type="selection" width="55" /> - <el-table-column prop="name" label="表名称" :show-overflow-tooltip="true" /> - <el-table-column prop="comment" label="表描述" :show-overflow-tooltip="true" /> + <el-table-column :show-overflow-tooltip="true" label="表名称" prop="name" /> + <el-table-column :show-overflow-tooltip="true" label="表描述" prop="comment" /> </el-table> </el-row> <!-- 操作 --> <template #footer> - <el-button @click="handleImportTable" type="primary" :disabled="tableList.length === 0"> + <el-button :disabled="tableList.length === 0" type="primary" @click="handleImportTable"> 导入 </el-button> <el-button @click="close">关闭</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraCodegenImportTable" setup> import * as CodegenApi from '@/api/infra/codegen' import * as DataSourceConfigApi from '@/api/infra/dataSourceConfig' import { ElTable } from 'element-plus' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/infra/codegen/PreviewCode.vue b/src/views/infra/codegen/PreviewCode.vue index 5dd3907b..339d9a53 100644 --- a/src/views/infra/codegen/PreviewCode.vue +++ b/src/views/infra/codegen/PreviewCode.vue @@ -1,48 +1,48 @@ <template> <Dialog - title="代码预览" v-model="dialogVisible" align-center - width="80%" class="app-infra-codegen-preview-container" + title="代码预览" + width="80%" > <div class="flex"> <!-- 代码目录树 --> <el-card - class="w-1/3" - :gutter="12" - shadow="hover" v-loading="loading" + :gutter="12" + class="w-1/3" element-loading-text="生成文件目录中..." + shadow="hover" > <el-scrollbar height="calc(100vh - 88px - 40px)"> <el-tree ref="treeRef" - node-key="id" :data="preview.fileTree" :expand-on-click-node="false" - highlight-current - @node-click="handleNodeClick" default-expand-all + highlight-current + node-key="id" + @node-click="handleNodeClick" /> </el-scrollbar> </el-card> <!-- 代码 --> <el-card - class="w-2/3 ml-3" - :gutter="12" - shadow="hover" v-loading="loading" + :gutter="12" + class="w-2/3 ml-3" element-loading-text="加载代码中..." + shadow="hover" > <el-tabs v-model="preview.activeName"> <el-tab-pane v-for="item in previewCodegen" + :key="item.filePath" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" :name="item.filePath" - :key="item.filePath" > - <el-button text type="primary" class="float-right" @click="copy(item.code)"> + <el-button class="float-right" text type="primary" @click="copy(item.code)"> {{ t('common.copy') }} </el-button> <div v-highlight> @@ -54,10 +54,11 @@ </div> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraCodegenPreviewCode" setup> import { useClipboard } from '@vueuse/core' import { handleTree2 } from '@/utils/tree' import * as CodegenApi from '@/api/infra/codegen' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/infra/codegen/components/BasicInfoForm.vue b/src/views/infra/codegen/components/BasicInfoForm.vue index 73174cbc..dcccd9e5 100644 --- a/src/views/infra/codegen/components/BasicInfoForm.vue +++ b/src/views/infra/codegen/components/BasicInfoForm.vue @@ -3,12 +3,12 @@ <el-row> <el-col :span="12"> <el-form-item label="表名称" prop="tableName"> - <el-input placeholder="请输入仓库名称" v-model="formData.tableName" /> + <el-input v-model="formData.tableName" placeholder="请输入仓库名称" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="表描述" prop="tableComment"> - <el-input placeholder="请输入" v-model="formData.tableComment" /> + <el-input v-model="formData.tableComment" placeholder="请输入" /> </el-form-item> </el-col> <el-col :span="12"> @@ -20,27 +20,27 @@ content="默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。" placement="top" > - <Icon icon="ep:question-filled" class="" /> + <Icon class="" icon="ep:question-filled" /> </el-tooltip> </span> </template> - <el-input placeholder="请输入" v-model="formData.className" /> + <el-input v-model="formData.className" placeholder="请输入" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="作者" prop="author"> - <el-input placeholder="请输入" v-model="formData.author" /> + <el-input v-model="formData.author" placeholder="请输入" /> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="备注" prop="remark"> - <el-input type="textarea" :rows="3" v-model="formData.remark" /> + <el-input v-model="formData.remark" :rows="3" type="textarea" /> </el-form-item> </el-col> </el-row> </el-form> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraCodegenBasicInfoForm" setup> import * as CodegenApi from '@/api/infra/codegen' import { PropType } from 'vue' diff --git a/src/views/infra/codegen/components/ColumInfoForm.vue b/src/views/infra/codegen/components/ColumInfoForm.vue index 5d2a036d..e228d3af 100644 --- a/src/views/infra/codegen/components/ColumInfoForm.vue +++ b/src/views/infra/codegen/components/ColumInfoForm.vue @@ -1,10 +1,10 @@ <template> - <el-table ref="dragTable" :data="formData" row-key="columnId" :max-height="tableHeight"> + <el-table ref="dragTable" :data="formData" :max-height="tableHeight" row-key="columnId"> <el-table-column - label="字段列名" - prop="columnName" - min-width="10%" :show-overflow-tooltip="true" + label="字段列名" + min-width="10%" + prop="columnName" /> <el-table-column label="字段描述" min-width="10%"> <template #default="scope"> @@ -12,10 +12,10 @@ </template> </el-table-column> <el-table-column - label="物理类型" - prop="dataType" - min-width="10%" :show-overflow-tooltip="true" + label="物理类型" + min-width="10%" + prop="dataType" /> <el-table-column label="Java类型" min-width="11%"> <template #default="scope"> @@ -37,26 +37,26 @@ </el-table-column> <el-table-column label="插入" min-width="4%"> <template #default="scope"> - <el-checkbox true-label="true" false-label="false" v-model="scope.row.createOperation" /> + <el-checkbox v-model="scope.row.createOperation" false-label="false" true-label="true" /> </template> </el-table-column> <el-table-column label="编辑" min-width="4%"> <template #default="scope"> - <el-checkbox true-label="true" false-label="false" v-model="scope.row.updateOperation" /> + <el-checkbox v-model="scope.row.updateOperation" false-label="false" true-label="true" /> </template> </el-table-column> <el-table-column label="列表" min-width="4%"> <template #default="scope"> <el-checkbox - true-label="true" - false-label="false" v-model="scope.row.listOperationResult" + false-label="false" + true-label="true" /> </template> </el-table-column> <el-table-column label="查询" min-width="4%"> <template #default="scope"> - <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperation" /> + <el-checkbox v-model="scope.row.listOperation" false-label="false" true-label="true" /> </template> </el-table-column> <el-table-column label="查询方式" min-width="10%"> @@ -75,7 +75,7 @@ </el-table-column> <el-table-column label="允许空" min-width="5%"> <template #default="scope"> - <el-checkbox true-label="true" false-label="false" v-model="scope.row.nullable" /> + <el-checkbox v-model="scope.row.nullable" false-label="false" true-label="true" /> </template> </el-table-column> <el-table-column label="显示类型" min-width="12%"> @@ -112,7 +112,7 @@ </el-table-column> </el-table> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraCodegenColumInfoForm" setup> import { PropType } from 'vue' import * as CodegenApi from '@/api/infra/codegen' import * as DictDataApi from '@/api/system/dict/dict.type' diff --git a/src/views/infra/codegen/components/GenerateInfoForm.vue b/src/views/infra/codegen/components/GenerateInfoForm.vue index b9898c09..51e01ad2 100644 --- a/src/views/infra/codegen/components/GenerateInfoForm.vue +++ b/src/views/infra/codegen/components/GenerateInfoForm.vue @@ -2,7 +2,7 @@ <el-form ref="formRef" :model="formData" :rules="rules" label-width="150px"> <el-row> <el-col :span="12"> - <el-form-item prop="templateType" label="生成模板"> + <el-form-item label="生成模板" prop="templateType"> <el-select v-model="formData.templateType" @change="tplSelectChange"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE)" @@ -14,7 +14,7 @@ </el-form-item> </el-col> <el-col :span="12"> - <el-form-item prop="frontType" label="前端类型"> + <el-form-item label="前端类型" prop="frontType"> <el-select v-model="formData.frontType"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE)" @@ -27,7 +27,7 @@ </el-col> <el-col :span="12"> - <el-form-item prop="scene" label="生成场景"> + <el-form-item label="生成场景" prop="scene"> <el-select v-model="formData.scene"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE)" @@ -50,11 +50,11 @@ </template> <el-tree-select v-model="formData.parentMenuId" - placeholder="请选择系统菜单" - node-key="id" - check-strictly :data="menus" :props="menuTreeProps" + check-strictly + node-key="id" + placeholder="请选择系统菜单" /> </el-form-item> </el-col> @@ -148,7 +148,7 @@ </el-form-item> </el-col> - <el-col :span="24" v-if="formData.genType === '1'"> + <el-col v-if="formData.genType === '1'" :span="24"> <el-form-item prop="genPath"> <template #label> <span> @@ -291,8 +291,8 @@ </el-row> </el-form> </template> -<script setup lang="ts"> -import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' +<script lang="ts" name="InfraCodegenGenerateInfoForm" setup> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { handleTree } from '@/utils/tree' import * as CodegenApi from '@/api/infra/codegen' import * as MenuApi from '@/api/system/menu' diff --git a/src/views/infra/config/ConfigForm.vue b/src/views/infra/config/ConfigForm.vue index f5eb1174..5c2d0283 100644 --- a/src/views/infra/config/ConfigForm.vue +++ b/src/views/infra/config/ConfigForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="参数分类" prop="category"> <el-input v-model="formData.category" placeholder="请输入参数分类" /> @@ -31,16 +31,16 @@ </el-radio-group> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraConfigForm" setup> import { DICT_TYPE, getBoolDictOptions } from '@/utils/dict' import * as ConfigApi from '@/api/infra/config' diff --git a/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue b/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue index b3ebb871..26a83583 100644 --- a/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue +++ b/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px" - v-loading="formLoading" > <el-form-item label="数据源名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入参数名称" /> @@ -21,12 +21,12 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraDataSourceConfigForm" setup> import * as DataSourceConfigApi from '@/api/infra/dataSourceConfig' const { t } = useI18n() // 国际化 diff --git a/src/views/infra/file/FileForm.vue b/src/views/infra/file/FileForm.vue index 5485870d..57fd147d 100644 --- a/src/views/infra/file/FileForm.vue +++ b/src/views/infra/file/FileForm.vue @@ -1,23 +1,23 @@ <template> - <Dialog title="上传文件" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="上传文件"> <el-upload ref="uploadRef" - :action="url" - :data="data" - :headers="uploadHeaders" v-model:file-list="fileList" - drag - accept=".jpg, .png, .gif" - :limit="1" - :on-success="submitFormSuccess" - :on-exceed="handleExceed" - :on-error="submitFormError" - :on-change="handleFileChange" + :action="url" :auto-upload="false" + :data="data" :disabled="formLoading" + :headers="uploadHeaders" + :limit="1" + :on-change="handleFileChange" + :on-error="submitFormError" + :on-exceed="handleExceed" + :on-success="submitFormSuccess" + accept=".jpg, .png, .gif" + drag > <i class="el-icon-upload"></i> - <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> + <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em></div> <template #tip> <div class="el-upload__tip" style="color: red"> 提示:仅允许导入 jpg、png、gif 格式文件! @@ -25,13 +25,14 @@ </template> </el-upload> <template #footer> - <el-button @click="submitFileForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitFileForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraFileForm" setup> import { getAccessToken, getTenantId } from '@/utils/auth' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/infra/fileConfig/FileConfigForm.vue b/src/views/infra/fileConfig/FileConfigForm.vue index 2f5a7586..42e0bbad 100644 --- a/src/views/infra/fileConfig/FileConfigForm.vue +++ b/src/views/infra/fileConfig/FileConfigForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="120px" - v-loading="formLoading" > <el-form-item label="配置名" prop="name"> <el-input v-model="formData.name" placeholder="请输入配置名" /> @@ -16,8 +16,8 @@ <el-form-item label="存储器" prop="storage"> <el-select v-model="formData.storage" - placeholder="请选择存储器" :disabled="formData.id !== undefined" + placeholder="请选择存储器" > <el-option v-for="dict in getDictOptions(DICT_TYPE.INFRA_FILE_STORAGE)" @@ -48,7 +48,7 @@ label="主机端口" prop="config.port" > - <el-input-number :min="0" v-model="formData.config.port" placeholder="请输入主机端口" /> + <el-input-number v-model="formData.config.port" :min="0" placeholder="请输入主机端口" /> </el-form-item> <el-form-item v-if="formData.storage >= 11 && formData.storage <= 12" @@ -93,14 +93,15 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraFileConfigForm" setup> import { DICT_TYPE, getDictOptions } from '@/utils/dict' import * as FileConfigApi from '@/api/infra/fileConfig' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/infra/job/JobDetail.vue b/src/views/infra/job/JobDetail.vue index 18e4235b..45bc4a5d 100644 --- a/src/views/infra/job/JobDetail.vue +++ b/src/views/infra/job/JobDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="任务详细" v-model="dialogVisible" width="700px"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" title="任务详细" width="700px"> + <el-descriptions :column="1" border> <el-descriptions-item label="任务编号" min-width="60"> {{ detailData.id }} </el-descriptions-item> @@ -42,7 +42,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraJobDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as JobApi from '@/api/infra/job' diff --git a/src/views/infra/job/logger/JobLogDetail.vue b/src/views/infra/job/logger/JobLogDetail.vue index 3b8795d9..a8ef8d4f 100644 --- a/src/views/infra/job/logger/JobLogDetail.vue +++ b/src/views/infra/job/logger/JobLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="任务详细" v-model="dialogVisible" width="700px"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" title="任务详细" width="700px"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志编号" min-width="60"> {{ detailData.id }} </el-descriptions-item> @@ -31,7 +31,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="JobLogDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as JobLogApi from '@/api/infra/jobLog' diff --git a/src/views/infra/webSocket/index.vue b/src/views/infra/webSocket/index.vue index b4e0acc0..c1690db2 100644 --- a/src/views/infra/webSocket/index.vue +++ b/src/views/infra/webSocket/index.vue @@ -1,6 +1,6 @@ <template> <div class="flex"> - <el-card class="w-1/2" :gutter="12" shadow="always"> + <el-card :gutter="12" class="w-1/2" shadow="always"> <template #header> <div class="card-header"> <span>连接</span> @@ -14,7 +14,7 @@ <div class="flex"> <el-input v-model="server" disabled> - <template #prepend> 服务地址 </template> + <template #prepend> 服务地址</template> </el-input> <el-button :type="getIsOpen ? 'danger' : 'primary'" @click="toggle"> {{ getIsOpen ? '关闭连接' : '开启连接' }} @@ -25,15 +25,15 @@ <el-input v-model="sendValue" :autosize="{ minRows: 2, maxRows: 4 }" - type="textarea" :disabled="!getIsOpen" clearable + type="textarea" /> - <el-button type="primary" block class="mt-4" :disabled="!getIsOpen" @click="handlerSend"> + <el-button :disabled="!getIsOpen" block class="mt-4" type="primary" @click="handlerSend"> 发送 </el-button> </el-card> - <el-card class="w-1/2" :gutter="12" shadow="always"> + <el-card :gutter="12" class="w-1/2" shadow="always"> <template #header> <div class="card-header"> <span>消息记录</span> @@ -41,7 +41,7 @@ </template> <div class="max-h-80 overflow-auto"> <ul> - <li v-for="item in getList" class="mt-2" :key="item.time"> + <li v-for="item in getList" :key="item.time" class="mt-2"> <div class="flex items-center"> <span class="mr-2 text-primary font-medium">收到消息:</span> <span>{{ formatDate(item.time) }}</span> @@ -55,7 +55,7 @@ </el-card> </div> </template> -<script setup lang="ts"> +<script lang="ts" name="InfraWebSocket" setup> import { formatDate } from '@/utils/formatTime' import { useUserStore } from '@/store/modules/user' import { useWebSocket } from '@vueuse/core' diff --git a/src/views/mall/product/property/PropertyForm.vue b/src/views/mall/product/property/PropertyForm.vue index 48832f76..c5955fc9 100644 --- a/src/views/mall/product/property/PropertyForm.vue +++ b/src/views/mall/product/property/PropertyForm.vue @@ -1,27 +1,28 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入名称" /> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ProductPropertyForm" setup> import * as PropertyApi from '@/api/mall/product/property' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/mall/product/property/value/ValueForm.vue b/src/views/mall/product/property/value/ValueForm.vue index 3f6a5225..3257cbc6 100644 --- a/src/views/mall/product/property/value/ValueForm.vue +++ b/src/views/mall/product/property/value/ValueForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="属性编号" prop="category"> <el-input v-model="formData.propertyId" disabled="" /> @@ -14,17 +14,18 @@ <el-input v-model="formData.name" placeholder="请输入名称" /> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="ProductPropertyValueForm" setup> import * as PropertyApi from '@/api/mall/product/property' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/mp/account/AccountForm.vue b/src/views/mp/account/AccountForm.vue index a80bb48f..f9c651ca 100644 --- a/src/views/mp/account/AccountForm.vue +++ b/src/views/mp/account/AccountForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="rules" label-width="120px" - v-loading="formLoading" > <el-form-item label="名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入名称" /> @@ -59,17 +59,18 @@ <el-input v-model="formData.aesKey" placeholder="请输入消息加解密密钥" /> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /> + <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="MpAccountForm" setup> import * as AccountApi from '@/api/mp/account' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/mp/components/wx-editor/WxEditor.vue b/src/views/mp/components/wx-editor/WxEditor.vue index 50c65c6e..52e9862f 100644 --- a/src/views/mp/components/wx-editor/WxEditor.vue +++ b/src/views/mp/components/wx-editor/WxEditor.vue @@ -1,5 +1,5 @@ -<script setup> -import { ref, reactive } from 'vue' +<script name="WxEditor" setup> +import { reactive, ref } from 'vue' import { QuillEditor } from '@vueup/vue-quill' import '@vueup/vue-quill/dist/vue-quill.snow.css' import { getAccessToken } from '@/utils/auth' @@ -88,21 +88,21 @@ const uploadError = () => { <div v-loading="loading" element-loading-text="请稍等,图片上传中"> <!-- 图片上传组件辅助--> <el-upload + :action="actionUrl" + :before-upload="beforeUpload" + :data="uploadData" + :headers="headers" + :on-error="uploadError" + :on-success="uploadSuccess" + :show-file-list="false" class="avatar-uploader" name="file" - :action="actionUrl" - :headers="headers" - :show-file-list="false" - :data="uploadData" - :on-success="uploadSuccess" - :on-error="uploadError" - :before-upload="beforeUpload" /> <QuillEditor - class="editor" - v-model="content" ref="quillEditorRef" + v-model="content" :options="editorOptions" + class="editor" @change="onEditorChange($event)" /> </div> diff --git a/src/views/mp/components/wx-news/main.vue b/src/views/mp/components/wx-news/main.vue index d08e2813..326b674c 100644 --- a/src/views/mp/components/wx-news/main.vue +++ b/src/views/mp/components/wx-news/main.vue @@ -9,13 +9,13 @@ <div class="news-home"> <div v-for="(article, index) in articles" :key="index" class="news-div"> <!-- 头条 --> - <a target="_blank" :href="article.url" v-if="index === 0"> + <a v-if="index === 0" :href="article.url" target="_blank"> <div class="news-main"> <div class="news-content"> <el-image + :src="article.picUrl" class="material-img" style="width: 100%; height: 120px" - :src="article.picUrl" /> <div class="news-content-title"> <span>{{ article.title }}</span> @@ -24,12 +24,12 @@ </div> </a> <!-- 二条/三条等等 --> - <a target="_blank" :href="article.url" v-else> + <a v-else :href="article.url" target="_blank"> <div class="news-main-item"> <div class="news-content-item"> <div class="news-content-item-title">{{ article.title }}</div> <div class="news-content-item-img"> - <img class="material-img" :src="article.picUrl" height="100%" /> + <img :src="article.picUrl" class="material-img" height="100%" /> </div> </div> </div> @@ -38,7 +38,7 @@ </div> </template> -<script setup lang="ts"> +<script lang="ts" name="WxNews" setup> const props = defineProps({ articles: { type: Array, @@ -57,15 +57,18 @@ defineExpose({ width: 100%; margin: auto; } + .news-main { width: 100%; margin: auto; } + .news-content { background-color: #acadae; width: 100%; position: relative; } + .news-content-title { display: inline-block; font-size: 12px; @@ -80,14 +83,17 @@ defineExpose({ white-space: normal; box-sizing: unset !important; } + .news-main-item { background-color: #ffffff; padding: 5px 0; border-top: 1px solid #eaeaea; } + .news-content-item { position: relative; } + .news-content-item-title { display: inline-block; font-size: 10px; @@ -95,12 +101,14 @@ defineExpose({ margin-left: 1%; white-space: normal; } + .news-content-item-img { display: inline-block; width: 25%; background-color: #acadae; margin-right: 1%; } + .material-img { width: 100%; } diff --git a/src/views/mp/tag/TagForm.vue b/src/views/mp/tag/TagForm.vue index e190af89..38af16e1 100644 --- a/src/views/mp/tag/TagForm.vue +++ b/src/views/mp/tag/TagForm.vue @@ -1,24 +1,25 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="标签名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入标签名称" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="MpTagForm" setup> import * as MpTagApi from '@/api/mp/tag' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/mp/user/UserForm.vue b/src/views/mp/user/UserForm.vue index a23d271f..612e4964 100644 --- a/src/views/mp/user/UserForm.vue +++ b/src/views/mp/user/UserForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog title="修改" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="修改"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="昵称" prop="nickname"> <el-input v-model="formData.nickname" placeholder="请输入昵称" /> @@ -14,7 +14,7 @@ <el-input v-model="formData.remark" placeholder="请输入备注" /> </el-form-item> <el-form-item label="标签" prop="tagIds"> - <el-select v-model="formData.tagIds" multiple clearable placeholder="请选择标签"> + <el-select v-model="formData.tagIds" clearable multiple placeholder="请选择标签"> <el-option v-for="item in tagList" :key="item.tagId" @@ -25,14 +25,15 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="MpUserForm" setup> import * as MpTagApi from '@/api/mp/tag' import * as MpUserApi from '@/api/mp/user' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/pay/app/AppForm.vue b/src/views/pay/app/AppForm.vue index 2e6c81da..a04ca49e 100644 --- a/src/views/pay/app/AppForm.vue +++ b/src/views/pay/app/AppForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="160px" - v-loading="formLoading" > <el-form-item label="应用名" prop="name"> <el-input v-model="formData.name" placeholder="请输入应用名" /> @@ -42,16 +42,17 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="PayAppForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as AppApi from '@/api/pay/app' import * as MerchantApi from '@/api/pay/merchant' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/pay/merchant/MerchantForm.vue b/src/views/pay/merchant/MerchantForm.vue index 34dea00a..8d86e3f0 100644 --- a/src/views/pay/merchant/MerchantForm.vue +++ b/src/views/pay/merchant/MerchantForm.vue @@ -1,5 +1,5 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px"> <el-form-item label="商户全称" prop="name"> <el-input v-model="formData.name" placeholder="请输入商户全称" /> @@ -8,7 +8,7 @@ <el-input v-model="formData.shortName" placeholder="请输入商户简称" /> </el-form-item> <el-form-item label="开启状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-select v-model="formData.status" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -18,19 +18,20 @@ </el-select> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /> + <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="PayMerchantForm" setup> import * as MerchantApi from '@/api/pay/merchant' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/pay/order/OrderDetail.vue b/src/views/pay/order/OrderDetail.vue index bb4bee74..ec2af786 100644 --- a/src/views/pay/order/OrderDetail.vue +++ b/src/views/pay/order/OrderDetail.vue @@ -1,5 +1,5 @@ <template> - <Dialog title="详情" v-model="dialogVisible" width="50%"> + <Dialog v-model="dialogVisible" title="详情" width="50%"> <el-descriptions :column="2"> <el-descriptions-item label="商户名称">{{ detailData.merchantName }}</el-descriptions-item> <el-descriptions-item label="应用名称">{{ detailData.appName }}</el-descriptions-item> @@ -66,7 +66,7 @@ </el-descriptions-item> </el-descriptions> <el-divider /> - <el-descriptions :column="1" direction="vertical" border> + <el-descriptions :column="1" border direction="vertical"> <el-descriptions-item label="商品描述"> {{ detailData.body }} </el-descriptions-item> @@ -78,7 +78,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts" name="orderForm"> +<script lang="ts" name="PayOrderDetail" setup> import { DICT_TYPE } from '@/utils/dict' import * as OrderApi from '@/api/pay/order' import { formatDate } from '@/utils/formatTime' diff --git a/src/views/pay/refund/RefundDetail.vue b/src/views/pay/refund/RefundDetail.vue index 8a47c6f6..4d241d98 100644 --- a/src/views/pay/refund/RefundDetail.vue +++ b/src/views/pay/refund/RefundDetail.vue @@ -1,5 +1,5 @@ <template> - <Dialog title="详情" v-model="dialogVisible" width="50%"> + <Dialog v-model="dialogVisible" title="详情" width="50%"> <el-descriptions :column="2"> <el-descriptions-item label="商户名称">{{ detailData.merchantName }}</el-descriptions-item> <el-descriptions-item label="应用名称">{{ detailData.appName }}</el-descriptions-item> @@ -76,7 +76,7 @@ </el-descriptions-item> </el-descriptions> <br /> - <el-descriptions :column="1" direction="vertical" border> + <el-descriptions :column="1" border direction="vertical"> <el-descriptions-item label="渠道额外参数"> {{ detailData.channelExtras }} </el-descriptions-item> @@ -84,7 +84,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts" name="refundForm"> +<script lang="ts" name="PayRefundDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as RefundApi from '@/api/pay/refund' diff --git a/src/views/system/area/AreaForm.vue b/src/views/system/area/AreaForm.vue index c0a51494..1610c9b9 100644 --- a/src/views/system/area/AreaForm.vue +++ b/src/views/system/area/AreaForm.vue @@ -1,27 +1,28 @@ <template> - <Dialog title="IP 查询" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="IP 查询"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="IP" prop="ip"> <el-input v-model="formData.ip" placeholder="请输入 IP 地址" /> </el-form-item> <el-form-item label="地址" prop="result"> - <el-input v-model="formData.result" readonly placeholder="展示查询 IP 结果" /> + <el-input v-model="formData.result" placeholder="展示查询 IP 结果" readonly /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemAreaForm" setup> import * as AreaApi from '@/api/system/area' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/system/dept/DeptForm.vue b/src/views/system/dept/DeptForm.vue index 92b4cb39..ec476a26 100644 --- a/src/views/system/dept/DeptForm.vue +++ b/src/views/system/dept/DeptForm.vue @@ -1,31 +1,31 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="上级部门" prop="parentId"> <el-tree-select v-model="formData.parentId" :data="deptTree" :props="defaultProps" - value-key="deptId" - placeholder="请选择上级部门" check-strictly default-expand-all + placeholder="请选择上级部门" + value-key="deptId" /> </el-form-item> <el-form-item label="部门名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入部门名称" /> </el-form-item> <el-form-item label="显示排序" prop="sort"> - <el-input-number v-model="formData.sort" controls-position="right" :min="0" /> + <el-input-number v-model="formData.sort" :min="0" controls-position="right" /> </el-form-item> <el-form-item label="负责人" prop="leaderUserId"> - <el-select v-model="formData.leaderUserId" placeholder="请输入负责人" clearable> + <el-select v-model="formData.leaderUserId" clearable placeholder="请输入负责人"> <el-option v-for="item in userList" :key="item.id" @@ -35,13 +35,13 @@ </el-select> </el-form-item> <el-form-item label="联系电话" prop="phone"> - <el-input v-model="formData.phone" placeholder="请输入联系电话" maxlength="11" /> + <el-input v-model="formData.phone" maxlength="11" placeholder="请输入联系电话" /> </el-form-item> <el-form-item label="邮箱" prop="email"> - <el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" /> + <el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-select v-model="formData.status" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -57,12 +57,13 @@ </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemDeptForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { handleTree, defaultProps } from '@/utils/tree' +import { defaultProps, handleTree } from '@/utils/tree' import * as DeptApi from '@/api/system/dept' import * as UserApi from '@/api/system/user' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/dict/DictTypeForm.vue b/src/views/system/dict/DictTypeForm.vue index bb0deb17..d9b7efd1 100644 --- a/src/views/system/dict/DictTypeForm.vue +++ b/src/views/system/dict/DictTypeForm.vue @@ -1,19 +1,19 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="字典名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入字典名称" /> </el-form-item> <el-form-item label="字典类型" prop="type"> <el-input - :disabled="typeof formData.id !== 'undefined'" v-model="formData.type" + :disabled="typeof formData.id !== 'undefined'" placeholder="请输入参数名称" /> </el-form-item> @@ -29,19 +29,20 @@ </el-radio-group> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemDictTypeForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as DictTypeApi from '@/api/system/dict/dict.type' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/dict/data/DictDataForm.vue b/src/views/system/dict/data/DictDataForm.vue index dc2f6057..c9d25916 100644 --- a/src/views/system/dict/data/DictDataForm.vue +++ b/src/views/system/dict/data/DictDataForm.vue @@ -1,16 +1,16 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="字典类型" prop="type"> <el-input - :disabled="typeof formData.id !== 'undefined'" v-model="formData.dictType" + :disabled="typeof formData.id !== 'undefined'" placeholder="请输入参数名称" /> </el-form-item> @@ -21,7 +21,7 @@ <el-input v-model="formData.value" placeholder="请输入数据键值" /> </el-form-item> <el-form-item label="显示排序" prop="sort"> - <el-input-number v-model="formData.sort" controls-position="right" :min="0" /> + <el-input-number v-model="formData.sort" :min="0" controls-position="right" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="formData.status"> @@ -48,19 +48,20 @@ <el-input v-model="formData.cssClass" placeholder="请输入 CSS Class" /> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemDictDataForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as DictDataApi from '@/api/system/dict/dict.data' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/errorCode/ErrorCodeForm.vue b/src/views/system/errorCode/ErrorCodeForm.vue index 3747ed06..9525a1a5 100644 --- a/src/views/system/errorCode/ErrorCodeForm.vue +++ b/src/views/system/errorCode/ErrorCodeForm.vue @@ -1,32 +1,32 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px" - v-loading="formLoading" > <el-form-item label="应用名" prop="applicationName"> - <el-input v-model="formData.applicationName" placeholder="请输入应用名" clearable /> + <el-input v-model="formData.applicationName" clearable placeholder="请输入应用名" /> </el-form-item> <el-form-item label="错误码编码" prop="code"> - <el-input v-model="formData.code" placeholder="请输入错误码编码" clearable /> + <el-input v-model="formData.code" clearable placeholder="请输入错误码编码" /> </el-form-item> <el-form-item label="错误码提示" prop="message"> - <el-input v-model="formData.message" placeholder="请输入错误码提示" clearable /> + <el-input v-model="formData.message" clearable placeholder="请输入错误码提示" /> </el-form-item> <el-form-item label="备注" prop="memo"> - <el-input v-model="formData.memo" placeholder="请输入备注" clearable /> + <el-input v-model="formData.memo" clearable placeholder="请输入备注" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemErrorCodeForm" setup> import * as ErrorCodeApi from '@/api/system/errorCode' const { t } = useI18n() // 国际化 diff --git a/src/views/system/loginlog/LoginLogDetail.vue b/src/views/system/loginlog/LoginLogDetail.vue index 3a8157ce..c59746b6 100644 --- a/src/views/system/loginlog/LoginLogDetail.vue +++ b/src/views/system/loginlog/LoginLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" width="800"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" title="详情" width="800"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志编号" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -25,7 +25,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemLoginLogDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as LoginLogApi from '@/api/system/loginLog' diff --git a/src/views/system/mail/account/MailAccountDetail.vue b/src/views/system/mail/account/MailAccountDetail.vue index b64c8d16..49bf98d6 100644 --- a/src/views/system/mail/account/MailAccountDetail.vue +++ b/src/views/system/mail/account/MailAccountDetail.vue @@ -1,9 +1,9 @@ <template> - <Dialog title="详情" v-model="dialogVisible"> - <Descriptions :schema="allSchemas.detailSchema" :data="detailData" /> + <Dialog v-model="dialogVisible" title="详情"> + <Descriptions :data="detailData" :schema="allSchemas.detailSchema" /> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMailAccountDetail" setup> import * as MailAccountApi from '@/api/system/mail/account' import { allSchemas } from './account.data' diff --git a/src/views/system/mail/account/MailAccountForm.vue b/src/views/system/mail/account/MailAccountForm.vue index fdc31dbd..53f12ac6 100644 --- a/src/views/system/mail/account/MailAccountForm.vue +++ b/src/views/system/mail/account/MailAccountForm.vue @@ -1,15 +1,16 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> - <Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules" v-loading="formLoading" /> + <Dialog v-model="dialogVisible" :title="dialogTitle"> + <Form ref="formRef" v-loading="formLoading" :rules="rules" :schema="allSchemas.formSchema" /> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMailAccountForm" setup> import * as MailAccountApi from '@/api/system/mail/account' -import { rules, allSchemas } from './account.data' +import { allSchemas, rules } from './account.data' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/mail/log/MailLogDetail.vue b/src/views/system/mail/log/MailLogDetail.vue index f781bc00..26c56bc1 100644 --- a/src/views/system/mail/log/MailLogDetail.vue +++ b/src/views/system/mail/log/MailLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500"> - <Descriptions :schema="allSchemas.detailSchema" :data="detailData"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情"> + <Descriptions :data="detailData" :schema="allSchemas.detailSchema"> <!-- 展示 HTML 内容 --> <template #templateContent="{ row }"> <div v-html="row.templateContent"></div> @@ -8,7 +8,7 @@ </Descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMailLogDetail" setup> import * as MailLogApi from '@/api/system/mail/log' import { allSchemas } from './log.data' diff --git a/src/views/system/mail/template/MailTemplateForm.vue b/src/views/system/mail/template/MailTemplateForm.vue index e35dcd7b..55367e16 100644 --- a/src/views/system/mail/template/MailTemplateForm.vue +++ b/src/views/system/mail/template/MailTemplateForm.vue @@ -1,21 +1,22 @@ <template> <Dialog - :title="dialogTitle" v-model="dialogVisible" - :scroll="true" - :width="800" :max-height="500" + :scroll="true" + :title="dialogTitle" + :width="800" > - <Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules" v-loading="formLoading" /> + <Form ref="formRef" v-loading="formLoading" :rules="rules" :schema="allSchemas.formSchema" /> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMailTemplateForm" setup> import * as MailTemplateApi from '@/api/system/mail/template' import { allSchemas, rules } from './template.data' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/mail/template/MailTemplateSendForm.vue b/src/views/system/mail/template/MailTemplateSendForm.vue index 01c98041..e900f1cb 100644 --- a/src/views/system/mail/template/MailTemplateSendForm.vue +++ b/src/views/system/mail/template/MailTemplateSendForm.vue @@ -1,14 +1,14 @@ <template> - <Dialog title="测试" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="测试"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="120px" - v-loading="formLoading" > <el-form-item label="模板内容" prop="content"> - <Editor :model-value="formData.content" readonly height="150px" /> + <Editor :model-value="formData.content" height="150px" readonly /> </el-form-item> <el-form-item label="收件邮箱" prop="mail"> <el-input v-model="formData.mail" placeholder="请输入收件邮箱" /> @@ -26,13 +26,14 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMailTemplateSendForm" setup> import * as MailTemplateApi from '@/api/system/mail/template' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/system/menu/MenuForm.vue b/src/views/system/menu/MenuForm.vue index 3e7b705c..278a9b51 100644 --- a/src/views/system/menu/MenuForm.vue +++ b/src/views/system/menu/MenuForm.vue @@ -1,24 +1,24 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px" - v-loading="formLoading" > <el-form-item label="上级菜单"> <el-tree-select - node-key="id" v-model="formData.parentId" - :props="defaultProps" :data="menuTree" :default-expanded-keys="[0]" + :props="defaultProps" check-strictly + node-key="id" /> </el-form-item> <el-form-item label="菜单名称" prop="name"> - <el-input v-model="formData.name" placeholder="请输入菜单名称" clearable /> + <el-input v-model="formData.name" clearable placeholder="请输入菜单名称" /> </el-form-item> <el-form-item label="菜单类型" prop="type"> <el-radio-group v-model="formData.type"> @@ -31,35 +31,35 @@ </el-radio-button> </el-radio-group> </el-form-item> - <el-form-item label="菜单图标" v-if="formData.type !== 3"> + <el-form-item v-if="formData.type !== 3" label="菜单图标"> <IconSelect v-model="formData.icon" clearable /> </el-form-item> - <el-form-item label="路由地址" prop="path" v-if="formData.type !== 3"> + <el-form-item v-if="formData.type !== 3" label="路由地址" prop="path"> <template #label> <Tooltip - titel="路由地址" message="访问的路由地址,如:`user`。如需外网地址时,则以 `http(s)://` 开头" + titel="路由地址" /> </template> - <el-input v-model="formData.path" placeholder="请输入路由地址" clearable /> + <el-input v-model="formData.path" clearable placeholder="请输入路由地址" /> </el-form-item> - <el-form-item label="组件地址" prop="component" v-if="formData.type === 2"> - <el-input v-model="formData.component" placeholder="例如说:system/user/index" clearable /> + <el-form-item v-if="formData.type === 2" label="组件地址" prop="component"> + <el-input v-model="formData.component" clearable placeholder="例如说:system/user/index" /> </el-form-item> - <el-form-item label="组件名字" prop="componentName" v-if="formData.type === 2"> - <el-input v-model="formData.componentName" placeholder="例如说:SystemUser" clearable /> + <el-form-item v-if="formData.type === 2" label="组件名字" prop="componentName"> + <el-input v-model="formData.componentName" clearable placeholder="例如说:SystemUser" /> </el-form-item> - <el-form-item label="权限标识" prop="permission" v-if="formData.type !== 1"> + <el-form-item v-if="formData.type !== 1" label="权限标识" prop="permission"> <template #label> <Tooltip - titel="权限标识" message="Controller 方法上的权限字符,如:@PreAuthorize(`@ss.hasPermission('system:user:list')`)" + titel="权限标识" /> </template> - <el-input v-model="formData.permission" placeholder="请输入权限标识" clearable /> + <el-input v-model="formData.permission" clearable placeholder="请输入权限标识" /> </el-form-item> <el-form-item label="显示排序" prop="sort"> - <el-input-number v-model="formData.sort" controls-position="right" :min="0" clearable /> + <el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" /> </el-form-item> <el-form-item label="菜单状态" prop="status"> <el-radio-group v-model="formData.status"> @@ -72,52 +72,53 @@ </el-radio> </el-radio-group> </el-form-item> - <el-form-item label="显示状态" prop="visible" v-if="formData.type !== 3"> + <el-form-item v-if="formData.type !== 3" label="显示状态" prop="visible"> <template #label> - <Tooltip titel="显示状态" message="选择隐藏时,路由将不会出现在侧边栏,但仍然可以访问" /> + <Tooltip message="选择隐藏时,路由将不会出现在侧边栏,但仍然可以访问" titel="显示状态" /> </template> <el-radio-group v-model="formData.visible"> - <el-radio border key="true" :label="true">显示</el-radio> - <el-radio border key="false" :label="false">隐藏</el-radio> + <el-radio key="true" :label="true" border>显示</el-radio> + <el-radio key="false" :label="false" border>隐藏</el-radio> </el-radio-group> </el-form-item> - <el-form-item label="总是显示" prop="alwaysShow" v-if="formData.type !== 3"> + <el-form-item v-if="formData.type !== 3" label="总是显示" prop="alwaysShow"> <template #label> <Tooltip - titel="总是显示" message="选择不是时,当该菜单只有一个子菜单时,不展示自己,直接展示子菜单" + titel="总是显示" /> </template> <el-radio-group v-model="formData.alwaysShow"> - <el-radio border key="true" :label="true">总是</el-radio> - <el-radio border key="false" :label="false">不是</el-radio> + <el-radio key="true" :label="true" border>总是</el-radio> + <el-radio key="false" :label="false" border>不是</el-radio> </el-radio-group> </el-form-item> - <el-form-item label="缓存状态" prop="keepAlive" v-if="formData.type === 2"> + <el-form-item v-if="formData.type === 2" label="缓存状态" prop="keepAlive"> <template #label> <Tooltip - titel="缓存状态" message="选择缓存时,则会被 `keep-alive` 缓存,必须填写「组件名称」字段" + titel="缓存状态" /> </template> <el-radio-group v-model="formData.keepAlive"> - <el-radio border key="true" :label="true">缓存</el-radio> - <el-radio border key="false" :label="false">不缓存</el-radio> + <el-radio key="true" :label="true" border>缓存</el-radio> + <el-radio key="false" :label="false" border>不缓存</el-radio> </el-radio-group> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemMenuForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as MenuApi from '@/api/system/menu' import { CACHE_KEY, useCache } from '@/hooks/web/useCache' -import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' -import { handleTree, defaultProps } from '@/utils/tree' +import { CommonStatusEnum, SystemMenuTypeEnum } from '@/utils/constants' +import { defaultProps, handleTree } from '@/utils/tree' + const { wsCache } = useCache() const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/notice/NoticeForm.vue b/src/views/system/notice/NoticeForm.vue index bf76c7d0..114a2c81 100644 --- a/src/views/system/notice/NoticeForm.vue +++ b/src/views/system/notice/NoticeForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible" width="800"> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="800"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="公告标题" prop="title"> <el-input v-model="formData.title" placeholder="请输入公告标题" /> @@ -14,7 +14,7 @@ <Editor :model-value="formData.content" height="150px" /> </el-form-item> <el-form-item label="公告类型" prop="type"> - <el-select v-model="formData.type" placeholder="请选择公告类型" clearable> + <el-select v-model="formData.type" clearable placeholder="请选择公告类型"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_NOTICE_TYPE)" :key="parseInt(dict.value)" @@ -24,7 +24,7 @@ </el-select> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-select v-model="formData.status" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="parseInt(dict.value)" @@ -34,19 +34,20 @@ </el-select> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输备注" /> + <el-input v-model="formData.remark" placeholder="请输备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemNoticeForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as NoticeApi from '@/api/system/notice' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/notify/message/NotifyMessageDetail.vue b/src/views/system/notify/message/NotifyMessageDetail.vue index 0a29ebb1..908d75a3 100644 --- a/src/views/system/notify/message/NotifyMessageDetail.vue +++ b/src/views/system/notify/message/NotifyMessageDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情"> + <el-descriptions :column="1" border> <el-descriptions-item label="编号" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -40,7 +40,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemNotifyMessageDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as NotifyMessageApi from '@/api/system/notify/message' diff --git a/src/views/system/notify/my/MyNotifyMessageDetail.vue b/src/views/system/notify/my/MyNotifyMessageDetail.vue index 247136b0..ad45d4eb 100644 --- a/src/views/system/notify/my/MyNotifyMessageDetail.vue +++ b/src/views/system/notify/my/MyNotifyMessageDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="消息详情" v-model="dialogVisible" :scroll="true" :max-height="500"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="消息详情"> + <el-descriptions :column="1" border> <el-descriptions-item label="发送人"> {{ detailData.templateNickname }} </el-descriptions-item> @@ -13,7 +13,7 @@ <el-descriptions-item label="是否已读"> <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="detailData.readStatus" /> </el-descriptions-item> - <el-descriptions-item label="阅读时间" v-if="detailData.readStatus"> + <el-descriptions-item v-if="detailData.readStatus" label="阅读时间"> {{ formatDate(detailData.readTime) }} </el-descriptions-item> <el-descriptions-item label="内容"> @@ -22,7 +22,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="MyNotifyMessageDetailDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as NotifyMessageApi from '@/api/system/notify/message' diff --git a/src/views/system/oauth2/client/ClientForm.vue b/src/views/system/oauth2/client/ClientForm.vue index b5936c37..d874a249 100644 --- a/src/views/system/oauth2/client/ClientForm.vue +++ b/src/views/system/oauth2/client/ClientForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible" scroll max-height="500px"> + <Dialog v-model="dialogVisible" :title="dialogTitle" max-height="500px" scroll> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="160px" - v-loading="formLoading" > <el-form-item label="客户端编号" prop="secret"> <el-input v-model="formData.clientId" placeholder="请输入客户端编号" /> @@ -20,7 +20,7 @@ <UploadImg v-model="formData.logo" :limit="1" /> </el-form-item> <el-form-item label="应用描述"> - <el-input type="textarea" v-model="formData.description" placeholder="请输入应用名" /> + <el-input v-model="formData.description" placeholder="请输入应用名" type="textarea" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="formData.status"> @@ -42,8 +42,8 @@ <el-form-item label="授权类型" prop="authorizedGrantTypes"> <el-select v-model="formData.authorizedGrantTypes" - multiple filterable + multiple placeholder="请输入授权类型" style="width: 500px" > @@ -58,9 +58,9 @@ <el-form-item label="授权范围" prop="scopes"> <el-select v-model="formData.scopes" - multiple - filterable allow-create + filterable + multiple placeholder="请输入授权范围" style="width: 500px" > @@ -70,8 +70,8 @@ <el-form-item label="自动授权范围" prop="autoApproveScopes"> <el-select v-model="formData.autoApproveScopes" - multiple filterable + multiple placeholder="请输入授权范围" style="width: 500px" > @@ -81,9 +81,9 @@ <el-form-item label="可重定向的 URI 地址" prop="redirectUris"> <el-select v-model="formData.redirectUris" - multiple - filterable allow-create + filterable + multiple placeholder="请输入可重定向的 URI 地址" style="width: 500px" > @@ -98,9 +98,9 @@ <el-form-item label="权限" prop="authorities"> <el-select v-model="formData.authorities" - multiple - filterable allow-create + filterable + multiple placeholder="请输入权限" style="width: 500px" > @@ -115,9 +115,9 @@ <el-form-item label="资源" prop="resourceIds"> <el-select v-model="formData.resourceIds" - multiple - filterable allow-create + filterable + multiple placeholder="请输入资源" style="width: 500px" > @@ -131,22 +131,23 @@ </el-form-item> <el-form-item label="附加信息" prop="additionalInformation"> <el-input - type="textarea" v-model="formData.additionalInformation" placeholder="请输入附加信息,JSON 格式数据" + type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemOAuth2ClientForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as ClientApi from '@/api/system/oauth2/client' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/operatelog/OperateLogDetail.vue b/src/views/system/operatelog/OperateLogDetail.vue index 1cf88663..f69af13a 100644 --- a/src/views/system/operatelog/OperateLogDetail.vue +++ b/src/views/system/operatelog/OperateLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情" width="800"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志主键" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -25,10 +25,10 @@ <el-descriptions-item label="操作名"> {{ detailData.name }} </el-descriptions-item> - <el-descriptions-item label="操作内容" v-if="detailData.content"> + <el-descriptions-item v-if="detailData.content" label="操作内容"> {{ detailData.content }} </el-descriptions-item> - <el-descriptions-item label="操作拓展参数" v-if="detailData.exts"> + <el-descriptions-item v-if="detailData.exts" label="操作拓展参数"> {{ detailData.exts }} </el-descriptions-item> <el-descriptions-item label="请求 URL"> @@ -48,16 +48,16 @@ <div v-if="detailData.resultCode === 0">正常</div> <div v-else>失败({{ detailData.resultCode }})</div> </el-descriptions-item> - <el-descriptions-item label="操作结果" v-if="detailData.resultCode === 0"> + <el-descriptions-item v-if="detailData.resultCode === 0" label="操作结果"> {{ detailData.resultData }} </el-descriptions-item> - <el-descriptions-item label="失败提示" v-if="detailData.resultCode > 0"> + <el-descriptions-item v-if="detailData.resultCode > 0" label="失败提示"> {{ detailData.resultMsg }} </el-descriptions-item> </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemOperateLogDetail" setup> import { formatDate } from '@/utils/formatTime' import * as OperateLogApi from '@/api/system/operatelog' diff --git a/src/views/system/post/PostForm.vue b/src/views/system/post/PostForm.vue index 586b86c6..e4ea8ad7 100644 --- a/src/views/system/post/PostForm.vue +++ b/src/views/system/post/PostForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible" width="800"> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="800"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="岗位标题" prop="name"> <el-input v-model="formData.name" placeholder="请输入岗位标题" /> @@ -17,7 +17,7 @@ <el-input v-model="formData.sort" placeholder="请输入岗位顺序" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-select v-model="formData.status" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -27,16 +27,16 @@ </el-select> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输备注" /> + <el-input v-model="formData.remark" placeholder="请输备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemPostForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as PostApi from '@/api/system/post' diff --git a/src/views/system/role/RoleAssignMenuForm.vue b/src/views/system/role/RoleAssignMenuForm.vue index cc8e2708..9b7d5a15 100644 --- a/src/views/system/role/RoleAssignMenuForm.vue +++ b/src/views/system/role/RoleAssignMenuForm.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="菜单权限" v-model="dialogVisible"> - <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading"> + <Dialog v-model="dialogVisible" title="菜单权限"> + <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px"> <el-form-item label="角色名称"> <el-tag>{{ formData.name }}</el-tag> </el-form-item> @@ -13,42 +13,43 @@ 全选/全不选: <el-switch v-model="treeNodeAll" - inline-prompt active-text="是" inactive-text="否" + inline-prompt @change="handleCheckedTreeNodeAll" /> 全部展开/折叠: <el-switch v-model="menuExpand" - inline-prompt active-text="展开" inactive-text="折叠" + inline-prompt @change="handleCheckedTreeExpand" /> </template> <el-tree ref="treeRef" + :data="menuOptions" + :props="defaultProps" + empty-text="加载中,请稍候" node-key="id" show-checkbox - :props="defaultProps" - :data="menuOptions" - empty-text="加载中,请稍候" /> </el-card> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> -import { handleTree, defaultProps } from '@/utils/tree' +<script lang="ts" name="SystemRoleAssignMenuForm" setup> +import { defaultProps, handleTree } from '@/utils/tree' import * as RoleApi from '@/api/system/role' import * as MenuApi from '@/api/system/menu' import * as PermissionApi from '@/api/system/permission' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/role/RoleDataPermissionForm.vue b/src/views/system/role/RoleDataPermissionForm.vue index 6b017278..87a33e6c 100644 --- a/src/views/system/role/RoleDataPermissionForm.vue +++ b/src/views/system/role/RoleDataPermissionForm.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="菜单权限" v-model="dialogVisible" width="800"> - <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading"> + <Dialog v-model="dialogVisible" title="菜单权限" width="800"> + <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px"> <el-form-item label="角色名称"> <el-tag>{{ formData.name }}</el-tag> </el-form-item> @@ -19,8 +19,8 @@ </el-form-item> </el-form> <el-form-item - label="权限范围" v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM" + label="权限范围" style="display: flex" > <el-card class="card" shadow="never"> @@ -28,47 +28,48 @@ 全选/全不选: <el-switch v-model="treeNodeAll" - inline-prompt active-text="是" inactive-text="否" + inline-prompt @change="handleCheckedTreeNodeAll()" /> 全部展开/折叠: <el-switch v-model="deptExpand" - inline-prompt active-text="展开" inactive-text="折叠" + inline-prompt @change="handleCheckedTreeExpand" /> 父子联动(选中父节点,自动选择子节点): - <el-switch v-model="checkStrictly" inline-prompt active-text="是" inactive-text="否" /> + <el-switch v-model="checkStrictly" active-text="是" inactive-text="否" inline-prompt /> </template> <el-tree ref="treeRef" + :check-strictly="!checkStrictly" + :data="deptOptions" + :props="defaultProps" + default-expand-all + empty-text="加载中,请稍后" node-key="id" show-checkbox - :check-strictly="!checkStrictly" - :props="defaultProps" - :data="deptOptions" - empty-text="加载中,请稍后" - default-expand-all /> </el-card> </el-form-item> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemRoleDataPermissionForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { handleTree, defaultProps } from '@/utils/tree' +import { defaultProps, handleTree } from '@/utils/tree' import { SystemDataScopeEnum } from '@/utils/constants' import * as RoleApi from '@/api/system/role' import * as DeptApi from '@/api/system/dept' import * as PermissionApi from '@/api/system/permission' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/role/RoleForm.vue b/src/views/system/role/RoleForm.vue index eecd2cdd..828d7f14 100644 --- a/src/views/system/role/RoleForm.vue +++ b/src/views/system/role/RoleForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="角色名称" prop="name"> <el-input v-model="formData.name" placeholder="请输入角色名称" /> @@ -17,7 +17,7 @@ <el-input v-model="formData.sort" placeholder="请输入显示顺序" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="formData.status" placeholder="请选择状态" clearable> + <el-select v-model="formData.status" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -27,19 +27,20 @@ </el-select> </el-form-item> <el-form-item label="备注" prop="remark"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输备注" /> + <el-input v-model="formData.remark" placeholder="请输备注" type="textarea" /> </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemRoleForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import * as RoleApi from '@/api/system/role' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue index 618a4990..4df19ef8 100644 --- a/src/views/system/role/index.vue +++ b/src/views/system/role/index.vue @@ -5,32 +5,32 @@ <ContentWrap> <!-- 搜索工作栏 --> <el-form - class="-mb-15px" - :model="queryParams" ref="queryFormRef" :inline="true" + :model="queryParams" + class="-mb-15px" label-width="68px" > <el-form-item label="角色名称" prop="name"> <el-input v-model="queryParams.name" - placeholder="请输入角色名称" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请输入角色名称" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="角色标识" prop="code"> <el-input v-model="queryParams.code" - placeholder="请输入角色标识" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请输入角色标识" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px"> + <el-select v-model="queryParams.status" class="!w-240px" clearable placeholder="请选择状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -42,33 +42,41 @@ <el-form-item label="创建时间" prop="createTime"> <el-date-picker v-model="queryParams.createTime" - value-format="YYYY-MM-DD HH:mm:ss" - type="daterange" - start-placeholder="开始日期" - end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" + end-placeholder="结束日期" + start-placeholder="开始日期" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" /> </el-form-item> <el-form-item> - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> - <el-button - type="primary" - plain - @click="openForm('create')" - v-hasPermi="['system:role:create']" - > - <Icon icon="ep:plus" class="mr-5px" /> 新增 + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 </el-button> <el-button - type="success" + v-hasPermi="['system:role:create']" plain - @click="handleExport" - :loading="exportLoading" - v-hasPermi="['system:role:export']" + type="primary" + @click="openForm('create')" > - <Icon icon="ep:download" class="mr-5px" /> 导出 + <Icon class="mr-5px" icon="ep:plus" /> + 新增 + </el-button> + <el-button + v-hasPermi="['system:role:export']" + :loading="exportLoading" + plain + type="success" + @click="handleExport" + > + <Icon class="mr-5px" icon="ep:download" /> + 导出 </el-button> </el-form-item> </el-form> @@ -77,59 +85,59 @@ <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list"> - <el-table-column label="角色编号" align="center" prop="id" /> - <el-table-column label="角色名称" align="center" prop="name" /> - <el-table-column label="角色类型" align="center" prop="type" /> - <el-table-column label="角色标识" align="center" prop="code" /> - <el-table-column label="显示顺序" align="center" prop="sort" /> - <el-table-column label="备注" align="center" prop="remark" /> - <el-table-column label="状态" align="center" prop="status"> + <el-table-column align="center" label="角色编号" prop="id" /> + <el-table-column align="center" label="角色名称" prop="name" /> + <el-table-column align="center" label="角色类型" prop="type" /> + <el-table-column align="center" label="角色标识" prop="code" /> + <el-table-column align="center" label="显示顺序" prop="sort" /> + <el-table-column align="center" label="备注" prop="remark" /> + <el-table-column align="center" label="状态" prop="status"> <template #default="scope"> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> </template> </el-table-column> <el-table-column - label="创建时间" + :formatter="dateFormatter" align="center" + label="创建时间" prop="createTime" width="180" - :formatter="dateFormatter" /> - <el-table-column :width="300" label="操作" align="center"> + <el-table-column :width="300" align="center" label="操作"> <template #default="scope"> <el-button + v-hasPermi="['system:role:update']" link type="primary" @click="openForm('update', scope.row.id)" - v-hasPermi="['system:role:update']" > 编辑 </el-button> <el-button + v-hasPermi="['system:permission:assign-role-menu']" link - type="primary" preIcon="ep:basketball" title="菜单权限" - v-hasPermi="['system:permission:assign-role-menu']" + type="primary" @click="openAssignMenuForm(scope.row)" > 菜单权限 </el-button> <el-button + v-hasPermi="['system:permission:assign-role-data-scope']" link - type="primary" preIcon="ep:coin" title="数据权限" - v-hasPermi="['system:permission:assign-role-data-scope']" + type="primary" @click="openDataPermissionForm(scope.row)" > 数据权限 </el-button> <el-button + v-hasPermi="['system:role:delete']" link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['system:role:delete']" > 删除 </el-button> @@ -138,9 +146,9 @@ </el-table> <!-- 分页 --> <Pagination - :total="total" - v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" @pagination="getList" /> </ContentWrap> @@ -152,7 +160,7 @@ <!-- 表单弹窗:数据权限 --> <RoleDataPermissionForm ref="dataPermissionFormRef" /> </template> -<script setup lang="tsx" name="SystemRole"> +<script lang="ts" name="SystemRole" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' @@ -160,6 +168,7 @@ import * as RoleApi from '@/api/system/role' import RoleForm from './RoleForm.vue' import RoleAssignMenuForm from './RoleAssignMenuForm.vue' import RoleDataPermissionForm from './RoleDataPermissionForm.vue' + const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 diff --git a/src/views/system/sensitiveWord/SensitiveWordForm.vue b/src/views/system/sensitiveWord/SensitiveWordForm.vue index aebaf6de..d9b5b78f 100644 --- a/src/views/system/sensitiveWord/SensitiveWordForm.vue +++ b/src/views/system/sensitiveWord/SensitiveWordForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="敏感词" prop="name"> <el-input v-model="formData.name" placeholder="请输入敏感词" /> @@ -27,9 +27,9 @@ <el-form-item label="标签" prop="tags"> <el-select v-model="formData.tags" - multiple - filterable allow-create + filterable + multiple placeholder="请选择文章标签" style="width: 380px" > @@ -38,15 +38,16 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts" name="SensitiveWordForm"> +<script lang="ts" name="SystemSensitiveWordForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as SensitiveWordApi from '@/api/system/sensitiveWord' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/sensitiveWord/SensitiveWordTestForm.vue b/src/views/system/sensitiveWord/SensitiveWordTestForm.vue index 80308033..93750603 100644 --- a/src/views/system/sensitiveWord/SensitiveWordTestForm.vue +++ b/src/views/system/sensitiveWord/SensitiveWordTestForm.vue @@ -1,21 +1,21 @@ <template> - <Dialog title="检测敏感词" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="检测敏感词"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="文本" prop="text"> - <el-input type="textarea" v-model="formData.text" placeholder="请输入测试文本" /> + <el-input v-model="formData.text" placeholder="请输入测试文本" type="textarea" /> </el-form-item> <el-form-item label="标签" prop="tags"> <el-select v-model="formData.tags" - multiple - filterable allow-create + filterable + multiple placeholder="请选择标签" style="width: 380px" > @@ -24,13 +24,14 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">检 测</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">检 测</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemSensitiveWordTestForm" setup> import * as SensitiveWordApi from '@/api/system/sensitiveWord' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/system/sensitiveWord/index.vue b/src/views/system/sensitiveWord/index.vue index 741d873c..921bde3e 100644 --- a/src/views/system/sensitiveWord/index.vue +++ b/src/views/system/sensitiveWord/index.vue @@ -2,34 +2,34 @@ <!-- 搜索工作栏 --> <ContentWrap> <el-form - class="-mb-15px" - :model="queryParams" ref="queryFormRef" :inline="true" + :model="queryParams" + class="-mb-15px" label-width="68px" > <el-form-item label="敏感词" prop="name"> <el-input v-model="queryParams.name" - placeholder="请输入敏感词" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请输入敏感词" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="标签" prop="tag"> <el-select v-model="queryParams.tag" - placeholder="请选择标签" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请选择标签" + @keyup.enter="handleQuery" > <el-option v-for="tag in tagList" :key="tag" :label="tag" :value="tag" /> </el-select> </el-form-item> <el-form-item label="状态" prop="status"> - <el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable> + <el-select v-model="queryParams.status" clearable placeholder="请选择启用状态"> <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" @@ -42,36 +42,45 @@ <el-form-item label="创建时间" prop="createTime"> <el-date-picker v-model="queryParams.createTime" - value-format="YYYY-MM-DD HH:mm:ss" - type="daterange" - start-placeholder="开始日期" - end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" + end-placeholder="结束日期" + start-placeholder="开始日期" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" /> </el-form-item> <el-form-item> - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 + </el-button> <el-button - type="primary" - plain - @click="openForm('create')" v-hasPermi="['system:sensitive-word:create']" + plain + type="primary" + @click="openForm('create')" > - <Icon icon="ep:plus" class="mr-5px" /> 新增 + <Icon class="mr-5px" icon="ep:plus" /> + 新增 </el-button> <el-button - type="success" - plain - @click="handleExport" - :loading="exportLoading" v-hasPermi="['system:sensitive-word:export']" + :loading="exportLoading" + plain + type="success" + @click="handleExport" > - <Icon icon="ep:download" class="mr-5px" /> 导出 + <Icon class="mr-5px" icon="ep:download" /> + 导出 </el-button> - <el-button type="warning" plain @click="openTestForm"> - <Icon icon="ep:document-checked" class="mr-5px" /> 测试 + <el-button plain type="warning" @click="openTestForm"> + <Icon class="mr-5px" icon="ep:document-checked" /> + 测试 </el-button> </el-form-item> </el-form> @@ -80,48 +89,48 @@ <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list"> - <el-table-column label="编号" align="center" prop="id" /> - <el-table-column label="敏感词" align="center" prop="name" /> - <el-table-column label="状态" align="center" prop="status"> + <el-table-column align="center" label="编号" prop="id" /> + <el-table-column align="center" label="敏感词" prop="name" /> + <el-table-column align="center" label="状态" prop="status"> <template #default="scope"> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> </template> </el-table-column> - <el-table-column label="描述" align="center" prop="description" /> - <el-table-column label="标签" align="center" prop="tags"> + <el-table-column align="center" label="描述" prop="description" /> + <el-table-column align="center" label="标签" prop="tags"> <template #default="scope"> <el-tag - class="mr-5px" v-for="tag in scope.row.tags" :key="tag" :disable-transitions="true" + class="mr-5px" > {{ tag }} </el-tag> </template> </el-table-column> <el-table-column - label="创建时间" + :formatter="dateFormatter" align="center" + label="创建时间" prop="createTime" width="180" - :formatter="dateFormatter" /> - <el-table-column label="操作" align="center"> + <el-table-column align="center" label="操作"> <template #default="scope"> <el-button + v-hasPermi="['infra:config:update']" link type="primary" @click="openForm('update', scope.row.id)" - v-hasPermi="['infra:config:update']" > 编辑 </el-button> <el-button + v-hasPermi="['infra:config:delete']" link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['infra:config:delete']" > 删除 </el-button> @@ -130,9 +139,9 @@ </el-table> <!-- 分页 --> <Pagination - :total="total" - v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" @pagination="getList" /> </ContentWrap> @@ -143,13 +152,14 @@ <!-- 表单弹窗:测试敏感词 --> <SensitiveWordTestForm ref="testFormRef" /> </template> -<script setup lang="ts" name="SystemSensitiveWordhao"> +<script lang="ts" name="SystemSensitiveWordHao" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' import * as SensitiveWordApi from '@/api/system/sensitiveWord' import SensitiveWordForm from './SensitiveWordForm.vue' import SensitiveWordTestForm from './SensitiveWordTestForm.vue' + const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 diff --git a/src/views/system/sms/channel/SmsChannelForm.vue b/src/views/system/sms/channel/SmsChannelForm.vue index cd491112..c5267393 100644 --- a/src/views/system/sms/channel/SmsChannelForm.vue +++ b/src/views/system/sms/channel/SmsChannelForm.vue @@ -1,17 +1,17 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="130px" - v-loading="formLoading" > <el-form-item label="短信签名" prop="signature"> <el-input v-model="formData.signature" placeholder="请输入短信签名" /> </el-form-item> <el-form-item label="渠道编码" prop="code"> - <el-select v-model="formData.code" placeholder="请选择渠道编码" clearable> + <el-select v-model="formData.code" clearable placeholder="请选择渠道编码"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE)" :key="dict.value" @@ -45,15 +45,16 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemSmsChannelForm" setup> import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' import * as SmsChannelApi from '@/api/system/sms/smsChannel' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/sms/log/SmsLogDetail.vue b/src/views/system/sms/log/SmsLogDetail.vue index 8a368b3e..bb63de03 100644 --- a/src/views/system/sms/log/SmsLogDetail.vue +++ b/src/views/system/sms/log/SmsLogDetail.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800"> - <el-descriptions border :column="1"> + <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情" width="800"> + <el-descriptions :column="1" border> <el-descriptions-item label="日志主键" min-width="120"> {{ detailData.id }} </el-descriptions-item> @@ -59,7 +59,7 @@ </el-descriptions> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemSmsLogDetail" setup> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' import * as SmsLogApi from '@/api/system/sms/smsLog' diff --git a/src/views/system/sms/template/SmsTemplateForm.vue b/src/views/system/sms/template/SmsTemplateForm.vue index 22de060a..91bf829a 100644 --- a/src/views/system/sms/template/SmsTemplateForm.vue +++ b/src/views/system/sms/template/SmsTemplateForm.vue @@ -1,22 +1,22 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="140px" - v-loading="formLoading" > <el-form-item label="短信渠道编号" prop="channelId"> <el-select v-model="formData.channelId" placeholder="请选择短信渠道编号"> <el-option v-for="channel in channelList" :key="channel.id" - :value="channel.id" :label=" channel.signature + `【 ${getDictLabel(DICT_TYPE.SYSTEM_SMS_CHANNEL_CODE, channel.code)}】` " + :value="channel.id" /> </el-select> </el-form-item> @@ -37,7 +37,7 @@ <el-input v-model="formData.name" placeholder="请输入模板名称" /> </el-form-item> <el-form-item label="模板内容" prop="content"> - <el-input type="textarea" v-model="formData.content" placeholder="请输入模板内容" /> + <el-input v-model="formData.content" placeholder="请输入模板内容" type="textarea" /> </el-form-item> <el-form-item label="开启状态" prop="status"> <el-radio-group v-model="formData.status"> @@ -58,16 +58,17 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> -import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict' +<script lang="ts" name="SystemSmsTemplateForm" setup> +import { DICT_TYPE, getDictLabel, getIntDictOptions } from '@/utils/dict' import * as SmsTemplateApi from '@/api/system/sms/smsTemplate' import * as SmsChannelApi from '@/api/system/sms/smsChannel' import { CommonStatusEnum } from '@/utils/constants' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/sms/template/SmsTemplateSendForm.vue b/src/views/system/sms/template/SmsTemplateSendForm.vue index 2da0e3f6..ec204ec3 100644 --- a/src/views/system/sms/template/SmsTemplateSendForm.vue +++ b/src/views/system/sms/template/SmsTemplateSendForm.vue @@ -1,18 +1,18 @@ <template> - <Dialog title="测试" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" title="测试"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="140px" - v-loading="formLoading" > <el-form-item label="模板内容" prop="content"> <el-input v-model="formData.content" - type="textarea" placeholder="请输入模板内容" readonly + type="textarea" /> </el-form-item> <el-form-item label="手机号" prop="mobile"> @@ -31,13 +31,14 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemSmsTemplateSendForm" setup> import * as SmsTemplateApi from '@/api/system/sms/smsTemplate' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 diff --git a/src/views/system/tenant/TenantForm.vue b/src/views/system/tenant/TenantForm.vue index ec19b487..c6bd6fec 100644 --- a/src/views/system/tenant/TenantForm.vue +++ b/src/views/system/tenant/TenantForm.vue @@ -1,17 +1,17 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%"> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="租户名" prop="name"> <el-input v-model="formData.name" placeholder="请输入租户名" /> </el-form-item> <el-form-item label="租户套餐" prop="packageId"> - <el-select v-model="formData.packageId" placeholder="请选择租户套餐" clearable> + <el-select v-model="formData.packageId" clearable placeholder="请选择租户套餐"> <el-option v-for="item in packageList" :key="item.id" @@ -33,25 +33,25 @@ <el-input v-model="formData.password" placeholder="请输入用户密码" - type="password" show-password + type="password" /> </el-form-item> <el-form-item label="账号额度" prop="accountCount"> <el-input-number v-model="formData.accountCount" - placeholder="请输入账号额度" - controls-position="right" :min="0" + controls-position="right" + placeholder="请输入账号额度" /> </el-form-item> <el-form-item label="过期时间" prop="expireTime"> <el-date-picker - clearable v-model="formData.expireTime" + clearable + placeholder="请选择过期时间" type="date" value-format="x" - placeholder="请选择过期时间" /> </el-form-item> <el-form-item label="绑定域名" prop="domain"> @@ -70,12 +70,12 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemTenantForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as TenantApi from '@/api/system/tenant' import { CommonStatusEnum } from '@/utils/constants' diff --git a/src/views/system/tenantPackage/TenantPackageForm.vue b/src/views/system/tenantPackage/TenantPackageForm.vue index becbcaab..d4230261 100644 --- a/src/views/system/tenantPackage/TenantPackageForm.vue +++ b/src/views/system/tenantPackage/TenantPackageForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-form-item label="套餐名" prop="name"> <el-input v-model="formData.name" placeholder="请输入套餐名" /> @@ -16,27 +16,27 @@ 全选/全不选: <el-switch v-model="treeNodeAll" - inline-prompt active-text="是" inactive-text="否" + inline-prompt @change="handleCheckedTreeNodeAll" /> 全部展开/折叠: <el-switch v-model="menuExpand" - inline-prompt active-text="展开" inactive-text="折叠" + inline-prompt @change="handleCheckedTreeExpand" /> </template> <el-tree ref="treeRef" + :data="menuOptions" + :props="defaultProps" + empty-text="加载中,请稍候" node-key="id" show-checkbox - :props="defaultProps" - :data="menuOptions" - empty-text="加载中,请稍候" /> </el-card> </el-form-item> @@ -56,18 +56,19 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts" name="TenantPackageForm"> +<script lang="ts" name="SystemTenantPackageForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import { defaultProps, handleTree } from '@/utils/tree' import * as TenantPackageApi from '@/api/system/tenantPackage' import * as MenuApi from '@/api/system/menu' import { ElTree } from 'element-plus' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/user/DeptTree.vue b/src/views/system/user/DeptTree.vue index 87ffaf9a..c7bc14ba 100644 --- a/src/views/system/user/DeptTree.vue +++ b/src/views/system/user/DeptTree.vue @@ -1,6 +1,6 @@ <template> <div class="head-container"> - <el-input v-model="deptName" placeholder="请输入部门名称" clearable class="mb-20px"> + <el-input v-model="deptName" class="mb-20px" clearable placeholder="请输入部门名称"> <template #prefix> <Icon icon="ep:search" /> </template> @@ -8,20 +8,20 @@ </div> <div class="head-container"> <el-tree + ref="treeRef" :data="deptList" - :props="defaultProps" - node-key="id" :expand-on-click-node="false" :filter-node-method="filterNode" - ref="treeRef" + :props="defaultProps" default-expand-all highlight-current + node-key="id" @node-click="handleNodeClick" /> </div> </template> -<script setup lang="ts" name="UserDeptTree"> +<script lang="ts" name="SystemUserDeptTree" setup> import { ElTree } from 'element-plus' import * as DeptApi from '@/api/system/dept' import { defaultProps, handleTree } from '@/utils/tree' diff --git a/src/views/system/user/UserAssignRoleForm.vue b/src/views/system/user/UserAssignRoleForm.vue index e0259b7d..a8e8fae3 100644 --- a/src/views/system/user/UserAssignRoleForm.vue +++ b/src/views/system/user/UserAssignRoleForm.vue @@ -1,6 +1,6 @@ <template> - <Dialog title="分配角色" v-model="dialogVisible"> - <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading"> + <Dialog v-model="dialogVisible" title="分配角色"> + <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px"> <el-form-item label="用户名称"> <el-input v-model="formData.username" :disabled="true" /> </el-form-item> @@ -14,15 +14,16 @@ </el-form-item> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script setup lang="ts"> +<script lang="ts" name="SystemUserAssignRoleForm" setup> import * as PermissionApi from '@/api/system/permission' import * as UserApi from '@/api/system/user' import * as RoleApi from '@/api/system/role' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/user/UserForm.vue b/src/views/system/user/UserForm.vue index 3afcbd1f..47dec515 100644 --- a/src/views/system/user/UserForm.vue +++ b/src/views/system/user/UserForm.vue @@ -1,11 +1,11 @@ <template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> + <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" + v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" - v-loading="formLoading" > <el-row> <el-col :span="12"> @@ -16,11 +16,11 @@ <el-col :span="12"> <el-form-item label="归属部门" prop="deptId"> <el-tree-select - node-key="id" v-model="formData.deptId" :data="deptList" :props="defaultProps" check-strictly + node-key="id" placeholder="请选择归属部门" /> </el-form-item> @@ -29,12 +29,12 @@ <el-row> <el-col :span="12"> <el-form-item label="手机号码" prop="mobile"> - <el-input v-model="formData.mobile" placeholder="请输入手机号码" maxlength="11" /> + <el-input v-model="formData.mobile" maxlength="11" placeholder="请输入手机号码" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="邮箱" prop="email"> - <el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" /> + <el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" /> </el-form-item> </el-col> </el-row> @@ -49,8 +49,8 @@ <el-input v-model="formData.password" placeholder="请输入用户密码" - type="password" show-password + type="password" /> </el-form-item> </el-col> @@ -84,24 +84,25 @@ <el-row> <el-col :span="24"> <el-form-item label="备注"> - <el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" /> + <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script lang="ts" setup> +<script lang="ts" name="SystemUserForm" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { CommonStatusEnum } from '@/utils/constants' import { defaultProps, handleTree } from '@/utils/tree' import * as PostApi from '@/api/system/post' import * as DeptApi from '@/api/system/dept' import * as UserApi from '@/api/system/user' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 diff --git a/src/views/system/user/UserImportForm.vue b/src/views/system/user/UserImportForm.vue index f03345e9..9890c00c 100644 --- a/src/views/system/user/UserImportForm.vue +++ b/src/views/system/user/UserImportForm.vue @@ -1,31 +1,32 @@ <template> - <Dialog title="用户导入" v-model="dialogVisible" width="400"> + <Dialog v-model="dialogVisible" title="用户导入" width="400"> <el-upload ref="uploadRef" - :action="importUrl + '?updateSupport=' + updateSupport" - :headers="uploadHeaders" v-model:file-list="fileList" - drag - accept=".xlsx, .xls" - :limit="1" - :on-success="submitFormSuccess" - :on-exceed="handleExceed" - :on-error="submitFormError" + :action="importUrl + '?updateSupport=' + updateSupport" :auto-upload="false" :disabled="formLoading" + :headers="uploadHeaders" + :limit="1" + :on-error="submitFormError" + :on-exceed="handleExceed" + :on-success="submitFormSuccess" + accept=".xlsx, .xls" + drag > <Icon icon="ep:upload" /> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> <template #tip> <div class="el-upload__tip text-center"> <div class="el-upload__tip"> - <el-checkbox v-model="updateSupport" /> 是否更新已经存在的用户数据 + <el-checkbox v-model="updateSupport" /> + 是否更新已经存在的用户数据 </div> <span>仅允许导入 xls、xlsx 格式文件。</span> <el-link - type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" + type="primary" @click="importTemplate" > 下载模板 @@ -34,15 +35,16 @@ </template> </el-upload> <template #footer> - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> -<script lang="ts" setup> +<script lang="ts" name="SystemUserImportForm" setup> import * as UserApi from '@/api/system/user' import { getAccessToken, getTenantId } from '@/utils/auth' import download from '@/utils/download' + const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 From 2bef7f707c6c8f262679398fddb8c88f761a213e Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Fri, 14 Apr 2023 21:46:34 +0800 Subject: [PATCH 02/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B2=A1=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84lang=3D"tsx"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/task/done/index.vue | 53 ++++++++++++++++------------- src/views/bpm/task/todo/index.vue | 55 +++++++++++++++++-------------- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/src/views/bpm/task/done/index.vue b/src/views/bpm/task/done/index.vue index ae3352d9..42d09c03 100644 --- a/src/views/bpm/task/done/index.vue +++ b/src/views/bpm/task/done/index.vue @@ -2,35 +2,41 @@ <ContentWrap> <!-- 搜索工作栏 --> <el-form - class="-mb-15px" - :model="queryParams" ref="queryFormRef" :inline="true" + :model="queryParams" + class="-mb-15px" label-width="68px" > <el-form-item label="任务名称" prop="name"> <el-input v-model="queryParams.name" - placeholder="请输入任务名称" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请输入任务名称" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="创建时间" prop="createTime"> <el-date-picker v-model="queryParams.createTime" - value-format="YYYY-MM-DD HH:mm:ss" - type="daterange" - start-placeholder="开始日期" - end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" + end-placeholder="结束日期" + start-placeholder="开始日期" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" /> </el-form-item> <el-form-item> - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 + </el-button> </el-form-item> </el-form> </ContentWrap> @@ -38,24 +44,24 @@ <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list"> - <el-table-column label="任务编号" align="center" prop="id" width="300px" /> - <el-table-column label="任务名称" align="center" prop="name" /> - <el-table-column label="所属流程" align="center" prop="processInstance.name" /> - <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" /> - <el-table-column label="状态" align="center" prop="result"> + <el-table-column align="center" label="任务编号" prop="id" width="300px" /> + <el-table-column align="center" label="任务名称" prop="name" /> + <el-table-column align="center" label="所属流程" prop="processInstance.name" /> + <el-table-column align="center" label="流程发起人" prop="processInstance.startUserNickname" /> + <el-table-column align="center" label="状态" prop="result"> <template #default="scope"> <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result" /> </template> </el-table-column> - <el-table-column label="原因" align="center" prop="reason" /> + <el-table-column align="center" label="原因" prop="reason" /> <el-table-column - label="创建时间" + :formatter="dateFormatter" align="center" + label="创建时间" prop="createTime" width="180" - :formatter="dateFormatter" /> - <el-table-column label="操作" align="center"> + <el-table-column align="center" label="操作"> <template #default="scope"> <el-button link type="primary" @click="openDetail(scope.row)">详情</el-button> <el-button link type="primary" @click="handleAudit(scope.row)">流程</el-button> @@ -64,9 +70,9 @@ </el-table> <!-- 分页 --> <Pagination - :total="total" - v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" @pagination="getList" /> </ContentWrap> @@ -74,11 +80,12 @@ <!-- 表单弹窗:详情 --> <TaskDetail ref="detailRef" @success="getList" /> </template> -<script setup lang="tsx" name="BpmTodoTask"> +<script lang="ts" name="BpmTodoTask" setup> import { DICT_TYPE } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import * as TaskApi from '@/api/bpm/task' import TaskDetail from './TaskDetail.vue' + const { push } = useRouter() // 路由 const loading = ref(true) // 列表的加载中 diff --git a/src/views/bpm/task/todo/index.vue b/src/views/bpm/task/todo/index.vue index 0bdc3850..ef2976e0 100644 --- a/src/views/bpm/task/todo/index.vue +++ b/src/views/bpm/task/todo/index.vue @@ -2,35 +2,41 @@ <ContentWrap> <!-- 搜索工作栏 --> <el-form - class="-mb-15px" - :model="queryParams" ref="queryFormRef" :inline="true" + :model="queryParams" + class="-mb-15px" label-width="68px" > <el-form-item label="任务名称" prop="name"> <el-input v-model="queryParams.name" - placeholder="请输入任务名称" - clearable - @keyup.enter="handleQuery" class="!w-240px" + clearable + placeholder="请输入任务名称" + @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="创建时间" prop="createTime"> <el-date-picker v-model="queryParams.createTime" - value-format="YYYY-MM-DD HH:mm:ss" - type="daterange" - start-placeholder="开始日期" - end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" + end-placeholder="结束日期" + start-placeholder="开始日期" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" /> </el-form-item> <el-form-item> - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 + </el-button> </el-form-item> </el-form> </ContentWrap> @@ -38,24 +44,24 @@ <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list"> - <el-table-column label="任务编号" align="center" prop="id" width="300px" /> - <el-table-column label="任务名称" align="center" prop="name" /> - <el-table-column label="所属流程" align="center" prop="processInstance.name" /> - <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" /> + <el-table-column align="center" label="任务编号" prop="id" width="300px" /> + <el-table-column align="center" label="任务名称" prop="name" /> + <el-table-column align="center" label="所属流程" prop="processInstance.name" /> + <el-table-column align="center" label="流程发起人" prop="processInstance.startUserNickname" /> <el-table-column - label="创建时间" + :formatter="dateFormatter" align="center" + label="创建时间" prop="createTime" width="180" - :formatter="dateFormatter" /> <el-table-column label="任务状态" prop="suspensionState"> <template #default="scope"> - <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag> - <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag> + <el-tag v-if="scope.row.suspensionState === 1" type="success">激活</el-tag> + <el-tag v-if="scope.row.suspensionState === 2" type="warning">挂起</el-tag> </template> </el-table-column> - <el-table-column label="操作" align="center"> + <el-table-column align="center" label="操作"> <template #default="scope"> <el-button link type="primary" @click="handleAudit(scope.row)">审批进度</el-button> </template> @@ -63,19 +69,20 @@ </el-table> <!-- 分页 --> <Pagination - :total="total" - v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" @pagination="getList" /> </ContentWrap> </template> -<script setup lang="tsx" name="BpmDoneTask"> +<script lang="ts" name="BpmDoneTask" setup> import { dateFormatter } from '@/utils/formatTime' -const { push } = useRouter() // 路由 import * as TaskApi from '@/api/bpm/task' +const { push } = useRouter() // 路由 + const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 From d62e607292a2bd12eafe5ad97fafcc726c99a019 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Fri, 14 Apr 2023 21:47:58 +0800 Subject: [PATCH 03/15] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E6=96=B9=E8=B7=B3=E8=BD=AC=E6=89=AB=E7=A0=81?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Profile/components/UserSocial.vue | 43 ++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/views/Profile/components/UserSocial.vue b/src/views/Profile/components/UserSocial.vue index da88d993..5d1664ea 100644 --- a/src/views/Profile/components/UserSocial.vue +++ b/src/views/Profile/components/UserSocial.vue @@ -1,30 +1,30 @@ <template> <el-table :data="socialUsers" :show-header="false"> - <el-table-column type="seq" title="序号" width="60" fixed="left" /> - <el-table-column label="社交平台" align="left" width="120"> + <el-table-column fixed="left" title="序号" type="seq" width="60" /> + <el-table-column align="left" label="社交平台" width="120"> <template #default="{ row }"> - <img class="h-5 align-middle" :src="row.img" alt="" /> + <img :src="row.img" alt="" class="h-5 align-middle" /> <p class="mr-5">{{ row.title }}</p> </template> </el-table-column> - <el-table-column label="操作" align="center"> + <el-table-column align="center" label="操作"> <template #default="{ row }"> <template v-if="row.openid"> 已绑定 - <XTextButton type="primary" class="mr-5" @click="unbind(row)" title="(解绑)" /> + <XTextButton class="mr-5" title="(解绑)" type="primary" @click="unbind(row)" /> </template> <template v-else> 未绑定 - <XTextButton type="primary" class="mr-5" @click="bind(row)" title="(绑定)" /> + <XTextButton class="mr-5" title="(绑定)" type="primary" @click="bind(row)" /> </template> </template> </el-table-column> </el-table> </template> -<script setup lang="ts"> +<script lang="ts" name="UserSocial" setup> import { SystemUserSocialTypeEnum } from '@/utils/constants' import { getUserProfile, ProfileVO } from '@/api/system/user/profile' -import { socialAuthRedirect, socialUnbind } from '@/api/system/user/socialUser' +import { socialAuthRedirect, socialBind, socialUnbind } from '@/api/system/user/socialUser' const message = useMessage() const socialUsers = ref<any[]>([]) @@ -46,11 +46,25 @@ const initSocial = async () => { } } } +const route = useRoute() +const bindSocial = () => { + // 社交绑定 + const type = route.query.type + const code = route.query.code + const state = route.query.state + if (!code) { + return + } + socialBind(type, code, state).then(() => { + message.success('绑定成功') + initSocial() + }) +} const bind = (row) => { const redirectUri = location.origin + '/user/profile?type=' + row.type // 进行跳转 socialAuthRedirect(row.type, encodeURIComponent(redirectUri)).then((res) => { - window.location.href = res.data + window.location.href = res }) } const unbind = async (row) => { @@ -64,4 +78,15 @@ const unbind = async (row) => { onMounted(async () => { await initSocial() }) + +watch( + () => route, + (newRoute) => { + bindSocial() + console.log(newRoute) + }, + { + immediate: true + } +) </script> From 7564c43f16167a93f477085d30be958e17c3c628 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Fri, 14 Apr 2023 22:06:27 +0800 Subject: [PATCH 04/15] =?UTF-8?q?=E6=94=B9editor=E4=B8=BAeditor=5F?= =?UTF-8?q?=E4=B8=80=E7=82=B9=E5=B0=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mp/components/wx-editor/WxEditor.vue | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/views/mp/components/wx-editor/WxEditor.vue b/src/views/mp/components/wx-editor/WxEditor.vue index 882924c0..7f42c5ee 100644 --- a/src/views/mp/components/wx-editor/WxEditor.vue +++ b/src/views/mp/components/wx-editor/WxEditor.vue @@ -1,5 +1,5 @@ <script name="WxEditor" setup> -import { ref, reactive } from 'vue' +import { reactive, ref } from 'vue' import { getAccessToken } from '@/utils/auth' import { Editor } from '@/components/Editor' @@ -83,21 +83,21 @@ const uploadError = () => { <div v-loading="loading" element-loading-text="请稍等,图片上传中"> <!-- 图片上传组件辅助--> <el-upload + :action="actionUrl" + :before-upload="beforeUpload" + :data="uploadData" + :headers="headers" + :on-error="uploadError" + :on-success="uploadSuccess" + :show-file-list="false" class="avatar-uploader" name="file" - :action="actionUrl" - :headers="headers" - :show-file-list="false" - :data="uploadData" - :on-success="uploadSuccess" - :on-error="uploadError" - :before-upload="beforeUpload" /> <Editor - editor-id="wxEditor" ref="quillEditorRef" :modelValue="content" - @change="(editor) => onEditorChange(editor.getText())" + editor-id="wxEditor" + @change="(editor_) => onEditorChange(editor_.getText())" /> </div> </div> From b26bba9939eac1d386f68706934ed5ae3944989c Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Fri, 14 Apr 2023 22:40:05 +0800 Subject: [PATCH 05/15] =?UTF-8?q?=E7=A7=BB=E9=99=A4vex=20hooks=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=AF=BC=E5=85=A5=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=89=93?= =?UTF-8?q?=E5=8C=85=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/vite/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/vite/index.ts b/build/vite/index.ts index 288ec93b..574a0d61 100644 --- a/build/vite/index.ts +++ b/build/vite/index.ts @@ -19,10 +19,12 @@ import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' export function createVitePlugins() { const root = process.cwd() + // 路径查找 function pathResolve(dir: string) { return resolve(root, '.', dir) } + return [ Vue(), VueJsx(), @@ -45,8 +47,6 @@ export function createVitePlugins() { { '@/hooks/web/useI18n': ['useI18n'], '@/hooks/web/useMessage': ['useMessage'], - '@/hooks/web/useXTable': ['useXTable'], - '@/hooks/web/useVxeCrudSchemas': ['useVxeCrudSchemas'], '@/hooks/web/useTable': ['useTable'], '@/hooks/web/useCrudSchemas': ['useCrudSchemas'], '@/utils/formRules': ['required'], From 18742b8cc70b365c8b089d6d86a74452b724a01b Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 09:13:25 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20css=20=E7=9A=84?= =?UTF-8?q?=E5=BC=95=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.ts | 7 ------- src/styles/index.scss | 1 - src/styles/variables.scss | 2 -- src/styles/vxe.css | 30 ------------------------------ src/utils/env.ts | 8 -------- 5 files changed, 48 deletions(-) delete mode 100644 src/styles/vxe.css delete mode 100644 src/utils/env.ts diff --git a/src/main.ts b/src/main.ts index 8dd1fff0..0fc15c2c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -37,8 +37,6 @@ import App from './App.vue' import './permission' -import { isDevMode } from '@/utils/env' - import { MyPD } from '@/components/bpmnProcessDesigner/package/index.js' import '@/components/bpmnProcessDesigner/package/theme/index.scss' import 'bpmn-js/dist/assets/diagram-js.css' @@ -53,11 +51,6 @@ import '@/plugins/tongji' // 百度统计 import Logger from '@/utils/Logger' -// 本地开发模式 全局引入 element-plus 样式,加快第一次进入速度 -if (isDevMode()) { - import('element-plus/dist/index.css') -} - // 创建实例 const setupAll = async () => { const app = createApp(App) diff --git a/src/styles/index.scss b/src/styles/index.scss index 39c4c4da..2781c12e 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -1,5 +1,4 @@ @import './var.css'; -@import './vxe.css'; @import 'element-plus/theme-chalk/dark/css-vars.css'; .reset-margin [class*='el-icon'] + span { diff --git a/src/styles/variables.scss b/src/styles/variables.scss index ffa78c9f..00b66f1f 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -2,5 +2,3 @@ $namespace: v; // el命名空间 $elNamespace: el; -// vxe命名空间 -$vxeNamespace: vxe; diff --git a/src/styles/vxe.css b/src/styles/vxe.css deleted file mode 100644 index 30bdd58d..00000000 --- a/src/styles/vxe.css +++ /dev/null @@ -1,30 +0,0 @@ -/*滚动条整体部分*/ -.xtable-scrollbar ::-webkit-scrollbar { - width: 10px; - height: 10px; -} -/*滚动条的轨道*/ -.xtable-scrollbar ::-webkit-scrollbar-track { - background-color: #ffffff; -} -/*滚动条里面的小方块,能向上向下移动*/ -.xtable-scrollbar ::-webkit-scrollbar-thumb { - background-color: #bfbfbf; - border-radius: 5px; - border: 1px solid #f1f1f1; - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); -} -.xtable-scrollbar ::-webkit-scrollbar-thumb:hover { - background-color: #a8a8a8; -} -.xtable-scrollbar ::-webkit-scrollbar-thumb:active { - background-color: #787878; -} -/*边角,即两个滚动条的交汇处*/ -.xtable-scrollbar ::-webkit-scrollbar-corner { - background-color: #ffffff; -} -/*移除 vxe-grid 右侧外框*/ -.vxe-button.size--medium.type--button.is--circle { - border: 0; -} diff --git a/src/utils/env.ts b/src/utils/env.ts deleted file mode 100644 index ea271813..00000000 --- a/src/utils/env.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const isDevMode = () => { - const dev = import.meta.env.VITE_DEV - if (dev && dev === 'true') { - return true - } else { - return false - } -} From 168f751a24a124e181e1fcc61a432082fbd862d8 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 09:19:37 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Vue3=20=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=90=8E=E5=8F=B0=E6=96=B0=E5=A2=9E=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E6=9C=AA=E6=A0=A1=E9=AA=8C=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E3=80=81=E5=AF=86=E7=A0=81=E6=98=AF=E5=90=A6=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/tenant/TenantForm.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/views/system/tenant/TenantForm.vue b/src/views/system/tenant/TenantForm.vue index ec19b487..5af895e7 100644 --- a/src/views/system/tenant/TenantForm.vue +++ b/src/views/system/tenant/TenantForm.vue @@ -105,7 +105,9 @@ const formRules = reactive({ status: [{ required: true, message: '租户状态不能为空', trigger: 'blur' }], accountCount: [{ required: true, message: '账号额度不能为空', trigger: 'blur' }], expireTime: [{ required: true, message: '过期时间不能为空', trigger: 'blur' }], - domain: [{ required: true, message: '绑定域名不能为空', trigger: 'blur' }] + domain: [{ required: true, message: '绑定域名不能为空', trigger: 'blur' }], + username: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }], + password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }] }) const formRef = ref() // 表单 Ref const packageList = ref([]) // 租户套餐 From de5b1216cd147efcaf7e310eca2fb06053592af8 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 10:28:23 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=92=8C=E7=B1=BB=E5=9E=8B=E7=9A=84=20status?= =?UTF-8?q?=20=E6=9C=AA=E6=A0=A1=E9=AA=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/dict/DictTypeForm.vue | 3 ++- src/views/system/dict/data/DictDataForm.vue | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/views/system/dict/DictTypeForm.vue b/src/views/system/dict/DictTypeForm.vue index bb0deb17..8cfc1b57 100644 --- a/src/views/system/dict/DictTypeForm.vue +++ b/src/views/system/dict/DictTypeForm.vue @@ -58,7 +58,8 @@ const formData = ref({ }) const formRules = reactive({ name: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }], - type: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }] + type: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }], + status: [{ required: true, message: '状态不能为空', trigger: 'change' }] }) const formRef = ref() // 表单 Ref diff --git a/src/views/system/dict/data/DictDataForm.vue b/src/views/system/dict/data/DictDataForm.vue index dc2f6057..337ee348 100644 --- a/src/views/system/dict/data/DictDataForm.vue +++ b/src/views/system/dict/data/DictDataForm.vue @@ -82,7 +82,8 @@ const formData = ref({ const formRules = reactive({ label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], value: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }], - sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }] + sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }], + status: [{ required: true, message: '状态不能为空', trigger: 'change' }] }) const formRef = ref() // 表单 Ref From 776eb3a7b0c619ec3b3b1ef3aece36d95781c96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=B1=E5=93=A5=E4=B8=B6?= <385454831@qq.com> Date: Sat, 15 Apr 2023 12:25:11 +0800 Subject: [PATCH 09/15] =?UTF-8?q?=E9=87=8D=E6=9E=84VUE3=E3=80=90=E7=AB=99?= =?UTF-8?q?=E5=86=85=E4=BF=A1-=E6=A8=A1=E6=9D=BF=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/notify/template/index.ts | 9 +- .../notify/template/NotifyTemplateForm.vue | 140 ++++++ src/views/system/notify/template/index.vue | 446 ++++++++++-------- .../system/notify/template/template.data.ts | 85 ---- 4 files changed, 407 insertions(+), 273 deletions(-) create mode 100644 src/views/system/notify/template/NotifyTemplateForm.vue delete mode 100644 src/views/system/notify/template/template.data.ts diff --git a/src/api/system/notify/template/index.ts b/src/api/system/notify/template/index.ts index 66530a90..f2bf5d27 100644 --- a/src/api/system/notify/template/index.ts +++ b/src/api/system/notify/template/index.ts @@ -1,13 +1,14 @@ import request from '@/config/axios' export interface NotifyTemplateVO { - id: number + id: number | null name: string + nickname: string code: string content: string - type: number + type: number | null params: string - status: number + status: number | null remark: string } @@ -19,7 +20,7 @@ export interface NotifyTemplatePageReqVO extends PageParam { } export interface NotifySendReqVO { - userId: number + userId: number | null templateCode: string templateParams: Map<String, Object> } diff --git a/src/views/system/notify/template/NotifyTemplateForm.vue b/src/views/system/notify/template/NotifyTemplateForm.vue new file mode 100644 index 00000000..d600a59c --- /dev/null +++ b/src/views/system/notify/template/NotifyTemplateForm.vue @@ -0,0 +1,140 @@ +<template> + <Dialog :title="dialogTitle" v-model="dialogVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="140px" + v-loading="formLoading" + > + <el-form-item label="模版编码" prop="code"> + <el-input v-model="formData.code" placeholder="请输入模版编码" /> + </el-form-item> + <el-form-item label="模板名称" prop="name"> + <el-input v-model="formData.name" placeholder="请输入模版名称" /> + </el-form-item> + <el-form-item label="发件人名称" prop="nickname"> + <el-input v-model="formData.nickname" placeholder="请输入发件人名称" /> + </el-form-item> + <el-form-item label="模板内容" prop="content"> + <el-input type="textarea" v-model="formData.content" placeholder="请输入模板内容" /> + </el-form-item> + <el-form-item label="类型" prop="type"> + <el-select v-model="formData.type" placeholder="请选择类型"> + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE)" + :key="dict.value" + :label="dict.label" + :value="parseInt(dict.value)" + /> + </el-select> + </el-form-item> + <el-form-item label="开启状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="parseInt(dict.value as string)" + > + {{ dict.label }} + </el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" placeholder="请输入备注" /> + </el-form-item> + </el-form> + <template #footer> + <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> + <el-button @click="dialogVisible = false">取 消</el-button> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import * as NotifyTemplateApi from '@/api/system/notify/template' +import { CommonStatusEnum } from '@/utils/constants' +const message = useMessage() // 消息弹窗 + +const dialogVisible = ref(false) // 弹窗的是否展示 +const dialogTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型 +const formData = ref<NotifyTemplateApi.NotifyTemplateVO>({ + id: null, + name: '', + nickname: '', + code: '', + content: '', + type: null, + params: '', + status: CommonStatusEnum.ENABLE, + remark: '' +}) +const formRules = reactive({ + type: [{ required: true, message: '消息类型不能为空', trigger: 'change' }], + status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }], + code: [{ required: true, message: '模板编码不能为空', trigger: 'blur' }], + name: [{ required: true, message: '模板名称不能为空', trigger: 'blur' }], + nickname: [{ required: true, message: '发件人姓名不能为空', trigger: 'blur' }], + content: [{ required: true, message: '模板内容不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +const open = async (type: string, id?: number) => { + dialogVisible.value = true + dialogTitle.value = type + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await NotifyTemplateApi.getNotifyTemplateApi(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + formLoading.value = true + try { + const data = formData.value as NotifyTemplateApi.NotifyTemplateVO + if (formType.value === 'create') { + await NotifyTemplateApi.createNotifyTemplateApi(data) + message.success('新增成功') + } else { + await NotifyTemplateApi.updateNotifyTemplateApi(data) + message.success('修改成功') + } + dialogVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: null, + name: '', + nickname: '', + code: '', + content: '', + type: null, + params: '', + status: CommonStatusEnum.ENABLE, + remark: '' + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/notify/template/index.vue b/src/views/system/notify/template/index.vue index 45c1be6d..9d37befb 100644 --- a/src/views/system/notify/template/index.vue +++ b/src/views/system/notify/template/index.vue @@ -1,87 +1,169 @@ <template> + <doc-alert title="站内信配置" url="https://doc.iocoder.cn/notify/" /> + <ContentWrap> - <!-- 列表 --> - <XTable @register="registerTable"> - <template #toolbar_buttons> - <!-- 操作:新增 --> - <XButton + <!-- 搜索工作栏 --> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > + <el-form-item label="模板名称" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入模板名称" + clearable + @keyup.enter="handleQuery" + class="!w-240px" + /> + </el-form-item> + <el-form-item label="模板编号" prop="code"> + <el-input + v-model="queryParams.code" + placeholder="请输入模版编码" + clearable + @keyup.enter="handleQuery" + class="!w-240px" + /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="请选择开启状态" + clearable + class="!w-240px" + > + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + value-format="YYYY-MM-DD HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> + <el-button type="primary" - preIcon="ep:zoom-in" - :title="t('action.add')" + plain + @click="openForm('create')" v-hasPermi="['system:notify-template:create']" - @click="handleCreate()" - /> - </template> - <template #actionbtns_default="{ row }"> - <!-- 操作:测试站内信 --> - <XTextButton - preIcon="ep:cpu" - :title="t('action.test')" - v-hasPermi="['system:notify-template:send-notify']" - @click="handleSendNotify(row)" - /> - <!-- 操作:修改 --> - <XTextButton - preIcon="ep:edit" - :title="t('action.edit')" - v-hasPermi="['system:notify-template:update']" - @click="handleUpdate(row.id)" - /> - <!-- 操作:详情 --> - <XTextButton - preIcon="ep:view" - :title="t('action.detail')" - v-hasPermi="['system:notify-template:query']" - @click="handleDetail(row.id)" - /> - <!-- 操作:删除 --> - <XTextButton - preIcon="ep:delete" - :title="t('action.del')" - v-hasPermi="['system:notify-template:delete']" - @click="deleteData(row.id)" - /> - </template> - </XTable> + > + <Icon icon="ep:plus" class="mr-5px" />新增 + </el-button> + </el-form-item> + </el-form> </ContentWrap> - <!-- 添加/修改的弹窗 --> - <Dialog id="templateModel" :loading="modelLoading" v-model="dialogVisible" :title="dialogTitle"> - <!-- 表单:添加/修改 --> - <Form - ref="formRef" - v-if="['create', 'update'].includes(actionType)" - :schema="allSchemas.formSchema" - :rules="rules" - /> - <!-- 表单:详情 --> - <Descriptions - v-if="actionType === 'detail'" - :schema="allSchemas.detailSchema" - :data="detailData" - /> - <template #footer> - <!-- 按钮:保存 --> - <XButton - v-if="['create', 'update'].includes(actionType)" - type="primary" - :title="t('action.save')" - :loading="actionLoading" - @click="submitForm()" + <!-- 列表 --> + <ContentWrap> + <el-table v-loading="loading" :data="list"> + <el-table-column + label="模板编码" + align="center" + prop="code" + width="120" + :show-overflow-tooltip="true" + /> + <el-table-column + label="模板名称" + align="center" + prop="name" + width="120" + :show-overflow-tooltip="true" + /> + <el-table-column label="类型" align="center" prop="type"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE" :value="scope.row.type" /> + </template> + </el-table-column> + <el-table-column label="发送人名称" align="center" prop="nickname" /> + <el-table-column + label="模板内容" + align="center" + prop="content" + width="200" + :show-overflow-tooltip="true" /> - <!-- 按钮:关闭 --> - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" /> - </template> - </Dialog> - <!-- 测试站内信的弹窗 --> - <Dialog id="sendTest" v-model="sendVisible" title="测试"> - <el-form :model="sendForm" :rules="sendRules" label-width="200px" label-position="top"> + <el-table-column label="开启状态" align="center" prop="status" width="80"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="备注" align="center" prop="remark" /> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + :formatter="dateFormatter" + /> + <el-table-column label="操作" align="center" width="210" fixed="right"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openForm('update', scope.row.id)" + v-hasPermi="['system:notify-template:update']" + > + 修改 + </el-button> + <el-button + link + type="primary" + @click="openSendForm(scope.row)" + v-hasPermi="['system:notify-template:send-notify']" + > + 测试 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['system:notify-template:delete']" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </ContentWrap> + + <Dialog v-model="dialogFormVisible" title="测试发送" :max-height="500"> + <el-form + ref="sendFormRef" + :model="sendFormData" + :rules="sendFormRules" + label-width="140px" + v-loading="formLoading" + > <el-form-item label="模板内容" prop="content"> - <el-input type="textarea" v-model="sendForm.content" readonly /> + <el-input v-model="sendFormData.content" readonly /> </el-form-item> <el-form-item label="接收人" prop="userId"> - <el-select v-model="sendForm.userId" placeholder="请选择接收人"> + <el-select v-model="sendFormData.userId" placeholder="请选择接收人"> <el-option v-for="item in userOption" :key="item.id" @@ -91,159 +173,155 @@ </el-select> </el-form-item> <el-form-item - v-for="param in sendForm.params" + v-for="param in sendFormData.params" :key="param" :label="'参数 {' + param + '}'" :prop="'templateParams.' + param" > <el-input - v-model="sendForm.templateParams[param]" + v-model="sendFormData.templateParams[param]" :placeholder="'请输入 ' + param + ' 参数'" /> </el-form-item> </el-form> - <!-- 操作按钮 --> <template #footer> - <XButton - type="primary" - :title="t('action.test')" - :loading="actionLoading" - @click="sendTest()" - /> - <XButton :title="t('dialog.close')" @click="sendVisible = false" /> + <span class="dialog-footer"> + <el-button @click="dialogFormVisible = false">取消</el-button> + <el-button type="primary" @click="submitForm"> 确定 </el-button> + </span> </template> </Dialog> + + <!-- 表单弹窗:添加/修改 --> + <NotifyTemplateForm ref="formRef" @success="getList" /> </template> -<script setup lang="ts" name="SystemNotifyTemplate"> -import { FormExpose } from '@/components/Form' -// 业务相关的 import -import { rules, allSchemas } from './template.data' +<script setup lang="ts" name="NotifySmsTemplate"> +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' import * as NotifyTemplateApi from '@/api/system/notify/template' import { getSimpleUserList, UserVO } from '@/api/system/user' +import NotifyTemplateForm from './NotifyTemplateForm.vue' -const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 -// 列表相关的变量 -const [registerTable, { reload, deleteData }] = useXTable({ - allSchemas: allSchemas, - getListApi: NotifyTemplateApi.getNotifyTemplatePageApi, - deleteApi: NotifyTemplateApi.deleteNotifyTemplateApi +const loading = ref(false) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 +const queryFormRef = ref() // 搜索的表单 + +const formLoading = ref(false) +const dialogFormVisible = ref(false) +const sendFormRef = ref() // 表单 Ref +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + name: undefined, + status: undefined, + code: undefined, + createTime: [] }) -// 弹窗相关的变量 -const dialogVisible = ref(false) // 是否显示弹出层 -const dialogTitle = ref('edit') // 弹出层标题 -const modelLoading = ref(false) // 弹出层loading -const actionType = ref('') // 操作按钮的类型 -const actionLoading = ref(false) // 按钮 Loading -const formRef = ref<FormExpose>() // 表单 Ref -const detailData = ref() // 详情 Ref - -// 设置标题 -const setDialogTile = (type: string) => { - modelLoading.value = true - dialogTitle.value = t('action.' + type) - actionType.value = type - dialogVisible.value = true -} - -// 新增操作 -const handleCreate = () => { - setDialogTile('create') - modelLoading.value = false -} - -// 修改操作 -const handleUpdate = async (rowId: number) => { - setDialogTile('update') - // 设置数据 - const res = await NotifyTemplateApi.getNotifyTemplateApi(rowId) - unref(formRef)?.setValues(res) - modelLoading.value = false -} - -// 详情操作 -const handleDetail = async (rowId: number) => { - setDialogTile('detail') - const res = await NotifyTemplateApi.getNotifyTemplateApi(rowId) - detailData.value = res - modelLoading.value = false -} - -// 提交按钮 -const submitForm = async () => { - const elForm = unref(formRef)?.getElFormRef() - if (!elForm) return - elForm.validate(async (valid) => { - if (valid) { - actionLoading.value = true - // 提交请求 - try { - const data = unref(formRef)?.formModel as NotifyTemplateApi.NotifyTemplateVO - if (actionType.value === 'create') { - await NotifyTemplateApi.createNotifyTemplateApi(data) - message.success(t('common.createSuccess')) - } else { - await NotifyTemplateApi.updateNotifyTemplateApi(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - } finally { - actionLoading.value = false - // 刷新列表 - await reload() - } - } - }) -} - -// ========== 测试相关 ========== -const sendForm = ref({ +const sendFormData = ref({ content: '', params: {}, - userId: 0, + userId: null, templateCode: '', templateParams: {} }) -const sendRules = ref({ - userId: [{ required: true, message: '用户编号不能为空', trigger: 'blur' }], + +const sendFormRules = ref({ + userId: [{ required: true, message: '用户编号不能为空', trigger: 'change' }], templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], templateParams: {} }) -const sendVisible = ref(false) + const userOption = ref<UserVO[]>([]) -const handleSendNotify = (row: any) => { - sendForm.value.content = row.content - sendForm.value.params = row.params - sendForm.value.templateCode = row.code - sendForm.value.templateParams = row.params.reduce(function (obj, item) { +/** 查询列表 */ +const getList = async () => { + loading.value = true + try { + const data = await NotifyTemplateApi.getNotifyTemplatePageApi(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ +const formRef = ref() +const openForm = (type: string, id?: number) => { + formRef.value.open(type, id) +} + +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await NotifyTemplateApi.deleteNotifyTemplateApi(id) + message.success('删除成功') + // 刷新列表 + await getList() + } catch {} +} + +const openSendForm = (row: any) => { + sendFormData.value.content = row.content + sendFormData.value.params = row.params + sendFormData.value.templateCode = row.code + sendFormData.value.templateParams = row.params.reduce(function (obj, item) { obj[item] = undefined return obj }, {}) - sendRules.value.templateParams = row.params.reduce(function (obj, item) { + sendFormRules.value.templateParams = row.params.reduce(function (obj, item) { obj[item] = { required: true, message: '参数 ' + item + ' 不能为空', trigger: 'change' } return obj }, {}) - sendVisible.value = true + dialogFormVisible.value = true } -const sendTest = async () => { - const data: NotifyTemplateApi.NotifySendReqVO = { - userId: sendForm.value.userId, - templateCode: sendForm.value.templateCode, - templateParams: sendForm.value.templateParams as unknown as Map<string, Object> +/** 提交表单 */ +const submitForm = async () => { + // 校验表单 + if (!sendFormRef) return + const valid = await sendFormRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data: NotifyTemplateApi.NotifySendReqVO = { + userId: sendFormData.value.userId, + templateCode: sendFormData.value.templateCode, + templateParams: sendFormData.value.templateParams as unknown as Map<string, Object> + } + const res = await NotifyTemplateApi.sendNotifyApi(data) + if (res) { + message.success('提交发送成功!发送结果,见消息记录编号:' + res) + } + dialogFormVisible.value = false + } finally { + formLoading.value = false } - const res = await NotifyTemplateApi.sendNotifyApi(data) - if (res) { - message.success('提交发送成功!发送结果,见发送日志编号:' + res) - } - sendVisible.value = false } -// ========== 初始化 ========== +/** 初始化 **/ onMounted(() => { + getList() getSimpleUserList().then((data) => { userOption.value = data }) diff --git a/src/views/system/notify/template/template.data.ts b/src/views/system/notify/template/template.data.ts deleted file mode 100644 index ae8c7b07..00000000 --- a/src/views/system/notify/template/template.data.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' - -// 表单校验 -export const rules = reactive({ - name: [required], - code: [required], - content: [required], - type: [required], - status: [required] -}) - -// CrudSchema -const crudSchemas = reactive<VxeCrudSchema>({ - primaryKey: 'id', - primaryTitle: '编号', - primaryType: null, - action: true, - actionWidth: '260', // 3个按钮默认200,如有删减对应增减即可 - columns: [ - { - title: '模版编码', - field: 'code', - isSearch: true - }, - { - title: '模板名称', - field: 'name', - isSearch: true - }, - { - title: '发件人名称', - field: 'nickname' - }, - { - title: '类型', - field: 'type', - dictType: DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE, - dictClass: 'number' - }, - { - title: '模版内容', - field: 'content', - table: { - width: 300 - }, - form: { - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - } - }, - { - title: '状态', - field: 'status', - dictType: DICT_TYPE.COMMON_STATUS, - dictClass: 'number', - isSearch: true - }, - { - title: '备注', - field: 'remark' - }, - { - title: '创建时间', - field: 'createTime', - isForm: false, - formatter: 'formatDate', - search: { - show: true, - itemRender: { - name: 'XDataTimePicker' - } - }, - table: { - width: 180 - } - } - ] -}) -export const { allSchemas } = useVxeCrudSchemas(crudSchemas) From 5910d53d8f42e565c3a5e14dc1048ad7063e9d95 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Sat, 15 Apr 2023 13:43:38 +0800 Subject: [PATCH 10/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B7=AE=E5=BC=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- src/types/.gitignore | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 src/types/.gitignore diff --git a/.gitignore b/.gitignore index ac15926b..0f033cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,6 @@ dist-ssr /dist* *-lock.* pnpm-debug - +auto-*.d.ts .idea .history diff --git a/src/types/.gitignore b/src/types/.gitignore deleted file mode 100644 index a00fe5dd..00000000 --- a/src/types/.gitignore +++ /dev/null @@ -1 +0,0 @@ -auto-*.d.ts From 389c73d834ad710c1398581314cb96787078b954 Mon Sep 17 00:00:00 2001 From: dhb52 <dhb52@126.com> Date: Sat, 15 Apr 2023 15:59:33 +0800 Subject: [PATCH 11/15] =?UTF-8?q?refactor:=20MP=E6=B6=88=E6=81=AF=E7=AE=A1?= =?UTF-8?q?=E7=90=86-=E6=8B=86=E5=88=86=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/mp/material/components/Upload.vue | 70 +++ .../mp/material/components/UploadVideo.vue | 127 ++++++ .../mp/material/components/VideoTable.vue | 61 +++ .../mp/material/components/VoiceTable.vue | 53 +++ .../mp/material/components/Waterfall.vue | 83 ++++ src/views/mp/material/components/upload.ts | 73 +++ src/views/mp/material/index.vue | 424 ++---------------- 7 files changed, 507 insertions(+), 384 deletions(-) create mode 100644 src/views/mp/material/components/Upload.vue create mode 100644 src/views/mp/material/components/UploadVideo.vue create mode 100644 src/views/mp/material/components/VideoTable.vue create mode 100644 src/views/mp/material/components/VoiceTable.vue create mode 100644 src/views/mp/material/components/Waterfall.vue create mode 100644 src/views/mp/material/components/upload.ts diff --git a/src/views/mp/material/components/Upload.vue b/src/views/mp/material/components/Upload.vue new file mode 100644 index 00000000..541dbc20 --- /dev/null +++ b/src/views/mp/material/components/Upload.vue @@ -0,0 +1,70 @@ +<template> + <el-upload + :action="UPLOAD_URL" + :headers="HEADERS" + multiple + :limit="1" + :file-list="fileList" + :data="uploadData" + :on-progress="() => (uploading = true)" + :before-upload="beforeUpload" + :on-success="handleUploadSuccess" + > + <el-button type="primary" plain :loading="uploading" :disabled="uploading"> + {{ uploading ? '正在上传' : '点击上传' }} + </el-button> + <template #tip> + <span class="el-upload__tip" style="margin-left: 5px"> + <slot></slot> + </span> + </template> + </el-upload> +</template> + +<script setup lang="ts"> +import type { UploadProps, UploadUserFile } from 'element-plus' +import { + HEADERS, + UPLOAD_URL, + UploadData, + MaterialType, + beforeImageUpload, + beforeVoiceUpload +} from './upload' + +const message = useMessage() + +const props = defineProps<{ type: boolean }>() + +const fileList = ref<UploadUserFile[]>([]) +const emit = defineEmits<{ + (e: 'uploaded', v: void) +}>() + +const uploadData: UploadData = reactive({ + type: MaterialType.Image, + title: '', + introduction: '' +}) +const uploading = ref(false) + +const beforeUpload = props.type == MaterialType.Image ? beforeImageUpload : beforeVoiceUpload + +const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { + if (res.code !== 0) { + message.alertError('上传出错:' + res.msg) + return false + } + + // 清空上传时的各种数据 + fileList.value = [] + uploadData.title = '' + uploadData.introduction = '' + + message.notifySuccess('上传成功') + uploading.value = false + emit('uploaded') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/UploadVideo.vue b/src/views/mp/material/components/UploadVideo.vue new file mode 100644 index 00000000..5da7d980 --- /dev/null +++ b/src/views/mp/material/components/UploadVideo.vue @@ -0,0 +1,127 @@ +<template> + <el-dialog title="新建视频" v-model="showDialog" width="600px" destroy-on-close> + <el-upload + :action="UPLOAD_URL" + :headers="HEADERS" + multiple + :limit="1" + :file-list="fileList" + :data="uploadData" + :before-upload="beforeVideoUpload" + :on-progress="() => (uploading = true)" + :on-success="handleUploadSuccess" + ref="uploadVideoRef" + :auto-upload="false" + class="mb-5" + > + <template #trigger> + <el-button type="primary" plain>选择视频</el-button> + </template> + <span class="el-upload__tip" style="margin-left: 10px" + >格式支持 MP4,文件大小不超过 10MB</span + > + </el-upload> + <el-divider /> + <el-form :model="uploadData" :rules="uploadRules" ref="uploadFormRef" v-loading="uploading"> + <el-form-item label="标题" prop="title"> + <el-input + v-model="uploadData.title" + placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" + /> + </el-form-item> + <el-form-item label="描述" prop="introduction"> + <el-input + :rows="3" + type="textarea" + v-model="uploadData.introduction" + placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" + /> + </el-form-item> + </el-form> + <template #footer> + <el-button @click="showDialog = false">取 消</el-button> + <el-button type="primary" @click="submitVideo" :loading="uploading" :disabled="uploading" + >提 交</el-button + > + </template> + </el-dialog> +</template> + +<script setup lang="ts"> +import type { + FormInstance, + FormRules, + UploadInstance, + UploadProps, + UploadUserFile +} from 'element-plus' +import { HEADERS, UploadData, UPLOAD_URL, beforeVideoUpload, MaterialType } from './upload' + +const message = useMessage() + +const uploadRules: FormRules = { + title: [{ required: true, message: '请输入标题', trigger: 'blur' }], + introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }] +} + +const props = defineProps({ + modelValue: { + type: Boolean, + default: false + } +}) +const emit = defineEmits<{ + (e: 'update:modelValue', v: boolean) + (e: 'uploaded', v: void) +}>() + +const showDialog = computed({ + get() { + return props.modelValue + }, + set(val) { + emit('update:modelValue', val) + } +}) + +const uploading = ref(false) + +const fileList = ref<UploadUserFile[]>([]) + +const uploadData: UploadData = reactive({ + type: MaterialType.Video, + title: '', + introduction: '' +}) + +const uploadFormRef = ref<FormInstance>() +const uploadVideoRef = ref<UploadInstance>() + +const submitVideo = () => { + uploadFormRef.value?.validate((valid) => { + if (!valid) { + return false + } + uploadVideoRef.value?.submit() + }) +} + +const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { + uploading.value = false + if (res.code !== 0) { + message.error('上传出错:' + res.msg) + return false + } + + // 清空上传时的各种数据 + fileList.value = [] + uploadData.title = '' + uploadData.introduction = '' + + showDialog.value = false + message.notifySuccess('上传成功') + emit('uploaded') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/VideoTable.vue b/src/views/mp/material/components/VideoTable.vue new file mode 100644 index 00000000..3bd2fe00 --- /dev/null +++ b/src/views/mp/material/components/VideoTable.vue @@ -0,0 +1,61 @@ +<template> + <el-table :data="props.list" stripe border v-loading="props.loading" style="margin-top: 10px"> + <el-table-column label="编号" align="center" prop="mediaId" /> + <el-table-column label="文件名" align="center" prop="name" /> + <el-table-column label="标题" align="center" prop="title" /> + <el-table-column label="介绍" align="center" prop="introduction" /> + <el-table-column label="视频" align="center"> + <template #default="scope"> + <WxVideoPlayer v-if="scope.row.url" :url="scope.row.url" /> + </template> + </el-table-column> + <el-table-column + label="上传时间" + align="center" + :formatter="dateFormatter" + prop="createTime" + width="180" + > + <template #default="scope"> + <span>{{ scope.row.createTime }}</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" fixed="right"> + <template #default="scope"> + <el-button type="primary" link @click="handleDownload(scope.row.url)"> + <Icon icon="ep:download" />下载 + </el-button> + <el-button + type="primary" + link + @click="emit('delete', scope.row.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" />删除 + </el-button> + </template> + </el-table-column> + </el-table> +</template> + +<script setup lang="ts"> +import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue' +import { dateFormatter } from '@/utils/formatTime' + +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) + (e: 'download', v: string) +}>() + +// 下载文件 +const handleDownload = (url: string) => { + window.open(url, '_blank') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/VoiceTable.vue b/src/views/mp/material/components/VoiceTable.vue new file mode 100644 index 00000000..44bd01da --- /dev/null +++ b/src/views/mp/material/components/VoiceTable.vue @@ -0,0 +1,53 @@ +<template> + <el-table :data="props.list" stripe border v-loading="props.loading" style="margin-top: 10px"> + <el-table-column label="编号" align="center" prop="mediaId" /> + <el-table-column label="文件名" align="center" prop="name" /> + <el-table-column label="语音" align="center"> + <template #default="scope"> + <WxVoicePlayer v-if="scope.row.url" :url="scope.row.url" /> + </template> + </el-table-column> + <el-table-column + label="上传时间" + align="center" + prop="createTime" + :formatter="dateFormatter" + width="180" + > + <template #default="scope"> + <span>{{ scope.row.createTime }}</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button type="primary" link @click="emit('delete', scope.row.id)"> + <Icon icon="ep:download" />下载 + </el-button> + <el-button + type="primary" + link + @click="emit('delete', scope.row.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" />删除 + </el-button> + </template> + </el-table-column> + </el-table> +</template> + +<script setup lang="ts"> +import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue' +import { dateFormatter } from '@/utils/formatTime' + +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) +}>() +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/Waterfall.vue b/src/views/mp/material/components/Waterfall.vue new file mode 100644 index 00000000..118fc7bd --- /dev/null +++ b/src/views/mp/material/components/Waterfall.vue @@ -0,0 +1,83 @@ +<template> + <div class="waterfall" v-loading="props.loading"> + <div class="waterfall-item" v-for="item in props.list" :key="item.id"> + <a target="_blank" :href="item.url"> + <img class="material-img" :src="item.url" /> + <div class="item-name">{{ item.name }}</div> + </a> + <el-row justify="center"> + <el-button + type="danger" + circle + @click="emit('delete', item.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" /> + </el-button> + </el-row> + </div> + </div> +</template> + +<script setup lang="ts"> +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) +}>() +</script> + +<style lang="scss" scoped> +/*瀑布流样式*/ +.waterfall { + width: 100%; + column-gap: 10px; + column-count: 5; + margin-top: 10px; + /* 芋道源码:增加 10px,避免顶着上面 */ +} + +.waterfall-item { + padding: 10px; + margin-bottom: 10px; + break-inside: avoid; + border: 1px solid #eaeaea; +} + +.material-img { + width: 100%; +} + +p { + line-height: 30px; +} + +@media (min-width: 992px) and (max-width: 1300px) { + .waterfall { + column-count: 3; + } + + p { + color: red; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .waterfall { + column-count: 2; + } + + p { + color: orange; + } +} + +@media (max-width: 767px) { + .waterfall { + column-count: 1; + } +} +</style> diff --git a/src/views/mp/material/components/upload.ts b/src/views/mp/material/components/upload.ts new file mode 100644 index 00000000..37441f5b --- /dev/null +++ b/src/views/mp/material/components/upload.ts @@ -0,0 +1,73 @@ +import type { UploadProps, UploadRawFile } from 'element-plus' +import { getAccessToken } from '@/utils/auth' + +const message = useMessage() + +const HEADERS = { Authorization: 'Bearer ' + getAccessToken() } +const UPLOAD_URL = 'http://127.0.0.1:8000/upload/' //import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' + +enum MaterialType { + Image = 'image', + Voice = 'voice', + Video = 'video' +} + +interface UploadData { + type: MaterialType + title: string + introduction: string +} + +const beforeUpload = (rawFile: UploadRawFile, materialType: MaterialType): boolean => { + let allowTypes: string[] = [] + let maxSizeMB = 0 + let name = '' + + switch (materialType) { + case MaterialType.Image: + allowTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'] + maxSizeMB = 2 + name = '图片' + break + case MaterialType.Voice: + allowTypes = ['audio/mp3', 'audio/mpeg', 'audio/wma', 'audio/wav', 'audio/amr'] + maxSizeMB = 2 + name = '图片' + break + case MaterialType.Video: + allowTypes = ['video/mp4'] + maxSizeMB = 10 + name = '视频' + } + + if (!allowTypes.includes(rawFile.type)) { + message.error(`上传${name}格式不对!`) + return false + } + + if (rawFile.size / 1024 / 1024 > maxSizeMB) { + message.error(`上传${name}大小不能超过${maxSizeMB}M!`) + return false + } + + return true +} + +const beforeImageUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Image) + +const beforeVoiceUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Voice) + +const beforeVideoUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Video) + +export { + HEADERS, + UPLOAD_URL, + MaterialType, + UploadData, + beforeImageUpload, + beforeVoiceUpload, + beforeVideoUpload +} diff --git a/src/views/mp/material/index.vue b/src/views/mp/material/index.vue index c6d8055d..dd54cf19 100644 --- a/src/views/mp/material/index.vue +++ b/src/views/mp/material/index.vue @@ -12,47 +12,18 @@ <ContentWrap> <el-tabs v-model="type" @tab-change="onTabChange"> <!-- tab 1:图片 --> - <el-tab-pane name="image"> + <el-tab-pane :name="MaterialType.Image"> <template #label> <span> <Icon icon="ep:picture" />图片 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :before-upload="beforeImageUpload" - :on-success="handleUploadSuccess" - > - <el-button type="primary" plain>点击上传</el-button> - <template #tip> - <span class="el-upload__tip" style="margin-left: 5px"> - 支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M - </span> - </template> - </el-upload> - </div> - <div class="waterfall" v-loading="loading"> - <div class="waterfall-item" v-for="item in list" :key="item.id"> - <a target="_blank" :href="item.url"> - <img class="material-img" :src="item.url" /> - <div class="item-name">{{ item.name }}</div> - </a> - <el-row justify="center"> - <el-button - type="danger" - circle - @click="handleDelete(item)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" /> - </el-button> - </el-row> - </div> - </div> + <Upload + v-hasPermi="['mp:material:upload-permanent']" + :type="MaterialType.Image" + @uploaded="getList" + > + 支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M + </Upload> + <Waterfall :loading="loading" :list="list" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -63,67 +34,20 @@ </el-tab-pane> <!-- tab 2:语音 --> - <el-tab-pane name="voice"> + <el-tab-pane :name="MaterialType.Voice"> <template #label> <span> <Icon icon="ep:microphone" />语音 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :on-success="handleUploadSuccess" - :before-upload="beforeVoiceUpload" - > - <el-button type="primary" plain>点击上传</el-button> - <template #tip> - <span class="el-upload__tip" style="margin-left: 5px"> - 格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s - </span> - </template> - </el-upload> - </div> + <Upload + v-hasPermi="['mp:material:upload-permanent']" + :type="MaterialType.Voice" + @uploaded="getList" + > + 格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s + </Upload> <!-- 列表 --> - <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px"> - <el-table-column label="编号" align="center" prop="mediaId" /> - <el-table-column label="文件名" align="center" prop="name" /> - <el-table-column label="语音" align="center"> - <template #default="scope"> - <WxVoicePlayer v-if="scope.row.url" :url="scope.row.url" /> - </template> - </el-table-column> - <el-table-column - label="上传时间" - align="center" - prop="createTime" - :formatter="dateFormatter" - width="180" - > - <template #default="scope"> - <span>{{ scope.row.createTime }}</span> - </template> - </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-button type="primary" link plain @click="handleDownload(scope.row)"> - <Icon icon="ep:download" />下载 - </el-button> - <el-button - type="primary" - link - plain - @click="handleDelete(scope.row)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" />删除 - </el-button> - </template> - </el-table-column> - </el-table> + <VoiceTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -134,105 +58,22 @@ </el-tab-pane> <!-- tab 3:视频 --> - <el-tab-pane name="video"> + <el-tab-pane :name="MaterialType.Video"> <template #label> <span> <Icon icon="ep:video-play" /> 视频 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-button type="primary" plain @click="handleAddVideo">新建视频</el-button> - </div> - <!-- 新建视频的弹窗 --> - <el-dialog - title="新建视频" - v-model="dialogVideoVisible" - width="600px" - v-loading="addMaterialLoading" + <el-button + v-hasPermi="['mp:material:upload-permanent']" + type="primary" + plain + @click="showCreateVideo = true" + >新建视频</el-button > - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :before-upload="beforeVideoUpload" - :on-success="handleUploadSuccess" - ref="uploadVideoRef" - :auto-upload="false" - > - <template #trigger> - <el-button size="small" type="primary">选择视频</el-button> - </template> - <span class="el-upload__tip" style="margin-left: 10px" - >格式支持 MP4,文件大小不超过 10MB</span - > - </el-upload> - <el-form :model="uploadData" :rules="uploadRules" ref="uploadFormRef" label-width="80px"> - <el-row> - <el-form-item label="标题" prop="title"> - <el-input - v-model="uploadData.title" - placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" - /> - </el-form-item> - </el-row> - <el-row> - <el-form-item label="描述" prop="introduction"> - <el-input - :rows="3" - type="textarea" - v-model="uploadData.introduction" - placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" - /> - </el-form-item> - </el-row> - </el-form> - <template #footer> - <el-button @click="cancelVideo">取 消</el-button> - <el-button type="primary" @click="submitVideo">提 交</el-button> - </template> - </el-dialog> + <!-- 新建视频的弹窗 --> + <UploadVideo v-model="showCreateVideo" /> <!-- 列表 --> - <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px"> - <el-table-column label="编号" align="center" prop="mediaId" /> - <el-table-column label="文件名" align="center" prop="name" /> - <el-table-column label="标题" align="center" prop="title" /> - <el-table-column label="介绍" align="center" prop="introduction" /> - <el-table-column label="视频" align="center"> - <template #default="scope"> - <WxVideoPlayer v-if="scope.row.url" :url="scope.row.url" /> - </template> - </el-table-column> - <el-table-column - label="上传时间" - align="center" - :formatter="dateFormatter" - prop="createTime" - width="180" - > - <template #default="scope"> - <span>{{ scope.row.createTime }}</span> - </template> - </el-table-column> - <el-table-column label="操作" align="center" fixed="right"> - <template #default="scope"> - <el-button type="primary" link plain @click="handleDownload(scope.row)"> - <Icon icon="ep:download" />下载 - </el-button> - <el-button - type="primary" - link - size="small" - plain - @click="handleDelete(scope.row)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" />删除 - </el-button> - </template> - </el-table-column> - </el-table> + <VideoTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -246,39 +87,19 @@ </template> <script lang="ts" setup name="MpMaterial"> -import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue' -import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue' import WxAccountSelect from '@/views/mp/components/wx-account-select/main.vue' +import Waterfall from './components/Waterfall.vue' +import VoiceTable from './components/VoiceTable.vue' +import VideoTable from './components/VideoTable.vue' +import Upload from './components/Upload.vue' +import UploadVideo from './components/UploadVideo.vue' +import { MaterialType } from './components/upload' import * as MpMaterialApi from '@/api/mp/material' -import * as authUtil from '@/utils/auth' -import { dateFormatter } from '@/utils/formatTime' -import type { - FormInstance, - FormRules, - TabPaneName, - UploadInstance, - UploadProps, - UploadRawFile, - UploadUserFile -} from 'element-plus' - -const BASE_URL = import.meta.env.VITE_BASE_URL -const uploadUrl = BASE_URL + '/admin-api/mp/material/upload-permanent' -const headers = { Authorization: 'Bearer ' + authUtil.getAccessToken() } const message = useMessage() -const uploadFormRef = ref<FormInstance>() -const uploadVideoRef = ref<UploadInstance>() - -const uploadRules: FormRules = { - title: [{ required: true, message: '请输入标题', trigger: 'blur' }], - introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }] -} - // 素材类型 -type MaterialType = 'image' | 'voice' | 'video' -const type = ref<MaterialType>('image') +const type = ref<MaterialType>(MaterialType.Image) const loading = ref(false) // 遮罩层 const list = ref<any[]>([]) // 总条数 const total = ref(0) // 数据列表 @@ -296,22 +117,8 @@ const queryParams: QueryParams = reactive({ permanent: true }) -const fileList = ref<UploadUserFile[]>([]) - -interface UploadData { - type: MaterialType - title: string - introduction: string -} -const uploadData: UploadData = reactive({ - type: 'image', - title: '', - introduction: '' -}) - // === 视频上传,独有变量 === -const dialogVideoVisible = ref(false) -const addMaterialLoading = ref(false) +const showCreateVideo = ref(false) /** 侦听公众号变化 **/ const onAccountChanged = (id?: number) => { @@ -341,10 +148,7 @@ const handleQuery = () => { getList() } -const onTabChange = (tabName: TabPaneName) => { - // 设置 type - uploadData.type = tabName as MaterialType - +const onTabChange = () => { // 提前情况数据,避免tab切换后显示垃圾数据 list.value = [] total.value = 0 @@ -353,160 +157,12 @@ const onTabChange = (tabName: TabPaneName) => { handleQuery() } -// ======================== 文件上传 ======================== -const beforeUpload = (rawFile: UploadRawFile, category: 'image' | 'audio' | 'video'): boolean => { - let allowTypes: string[] = [] - let maxSizeMB = 0 - let name = '' - - switch (category) { - case 'image': - allowTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'] - maxSizeMB = 2 - name = '图片' - break - case 'audio': - allowTypes = ['audio/mp3', 'audio/mpeg', 'audio/wma', 'audio/wav', 'audio/amr'] - maxSizeMB = 2 - name = '图片' - break - case 'video': - allowTypes = ['video/mp4'] - maxSizeMB = 10 - name = '视频' - } - - if (!allowTypes.includes(rawFile.type)) { - message.error(`上传${name}格式不对!`) - return false - } - // 校验大小 - if (rawFile.size / 1024 / 1024 > maxSizeMB) { - message.error(`上传${name}大小不能超过${maxSizeMB}M!`) - return false - } - loading.value = true - return true -} - -const beforeImageUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'image') - -const beforeVoiceUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'audio') - -const beforeVideoUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'video') - -const handleUploadSuccess: UploadProps['onSuccess'] = (response: any) => { - loading.value = false - addMaterialLoading.value = false - if (response.code !== 0) { - message.error('上传出错:' + response.msg) - return false - } - - // 清空上传时的各种数据 - dialogVideoVisible.value = false - fileList.value = [] - uploadData.title = '' - uploadData.introduction = '' - - // 加载数据 - getList() -} - -// 下载文件 -const handleDownload = (row: any) => { - window.open(row.url, '_blank') -} - -// 提交 video 新建的表单 -const submitVideo = () => { - uploadFormRef.value?.validate((valid) => { - if (!valid) { - return false - } - uploadVideoRef.value?.submit() - }) -} - -// 弹出 video 新建的表单 -const handleAddVideo = () => { - resetVideo() - dialogVideoVisible.value = true -} - -/** 取消按钮 */ -const cancelVideo = () => { - dialogVideoVisible.value = false - resetVideo() -} - -/** 表单重置 */ -const resetVideo = () => { - fileList.value = [] - uploadData.title = '' - uploadData.introduction = '' - uploadFormRef.value?.resetFields() -} - // ======================== 其它操作 ======================== -const handleDelete = async (item: any) => { +const handleDelete = async (id: number) => { await message.confirm('此操作将永久删除该文件, 是否继续?') - await MpMaterialApi.deletePermanentMaterial(item.id) + await MpMaterialApi.deletePermanentMaterial(id) message.alertSuccess('删除成功') } </script> -<style lang="scss" scoped> -/*瀑布流样式*/ -.waterfall { - width: 100%; - column-gap: 10px; - column-count: 5; - margin-top: 10px; - /* 芋道源码:增加 10px,避免顶着上面 */ -} - -.waterfall-item { - padding: 10px; - margin-bottom: 10px; - break-inside: avoid; - border: 1px solid #eaeaea; -} - -.material-img { - width: 100%; -} - -p { - line-height: 30px; -} - -@media (min-width: 992px) and (max-width: 1300px) { - .waterfall { - column-count: 3; - } - - p { - color: red; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .waterfall { - column-count: 2; - } - - p { - color: orange; - } -} - -@media (max-width: 767px) { - .waterfall { - column-count: 1; - } -} -</style> +<style lang="scss" scoped></style> From 4dabb710c557345ed5e3c391ebd8e77eb818deb3 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 16:03:12 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E4=BC=98=E5=8C=96=20OA=20=E8=AF=B7?= =?UTF-8?q?=E5=81=87=EF=BC=8Ccreate=20=E5=92=8C=20detail=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=8B=AC=E7=AB=8B=E8=B7=AF=E7=94=B1=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/modules/remaining.ts | 14 +++- src/views/bpm/oa/leave/create.vue | 113 ++++++++++++------------------ src/views/bpm/oa/leave/detail.vue | 34 +++++---- src/views/bpm/oa/leave/index.vue | 20 +++--- 4 files changed, 88 insertions(+), 93 deletions(-) diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 8886e388..d3b18d9c 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -313,7 +313,19 @@ const remainingRouter: AppRouteRecordRaw[] = [ hidden: true, canTo: true, title: '发起 OA 请假', - activeMenu: 'bpm/oa/leave/create' + activeMenu: '/bpm/oa/leave' + } + }, + { + path: '/bpm/oa/leave/detail', + component: () => import('@/views/bpm/oa/leave/detail.vue'), + name: 'OALeaveDetail', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '查看 OA 请假', + activeMenu: '/bpm/oa/leave' } } ] diff --git a/src/views/bpm/oa/leave/create.vue b/src/views/bpm/oa/leave/create.vue index 321ec609..13c49419 100644 --- a/src/views/bpm/oa/leave/create.vue +++ b/src/views/bpm/oa/leave/create.vue @@ -1,56 +1,55 @@ <template> - <Dialog title="发起 OA 请假流程" v-model="dialogVisible"> - <el-form - ref="formRef" - :model="formData" - :rules="formRules" - label-width="80px" - v-loading="formLoading" - > - <el-form-item label="请假类型" prop="type"> - <el-select v-model="formData.type" placeholder="请选择请假类型" clearable> - <el-option - v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - <el-form-item label="开始时间" prop="startTime"> - <el-date-picker - clearable - v-model="formData.startTime" - type="datetime" - value-format="x" - placeholder="请选择开始时间" + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="80px" + v-loading="formLoading" + > + <el-form-item label="请假类型" prop="type"> + <el-select v-model="formData.type" placeholder="请选择请假类型" clearable> + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)" + :key="dict.value" + :label="dict.label" + :value="dict.value" /> - </el-form-item> - <el-form-item label="结束时间" prop="endTime"> - <el-date-picker - clearable - v-model="formData.endTime" - type="datetime" - value-format="x" - placeholder="请选择结束时间" - /> - </el-form-item> - <el-form-item label="原因" prop="reason"> - <el-input v-model="formData.reason" type="textarea" placeholder="请输请假原因" /> - </el-form-item> - </el-form> - <template #footer> + </el-select> + </el-form-item> + <el-form-item label="开始时间" prop="startTime"> + <el-date-picker + clearable + v-model="formData.startTime" + type="datetime" + value-format="x" + placeholder="请选择开始时间" + /> + </el-form-item> + <el-form-item label="结束时间" prop="endTime"> + <el-date-picker + clearable + v-model="formData.endTime" + type="datetime" + value-format="x" + placeholder="请选择结束时间" + /> + </el-form-item> + <el-form-item label="原因" prop="reason"> + <el-input v-model="formData.reason" type="textarea" placeholder="请输请假原因" /> + </el-form-item> + <el-form-item> <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> - <el-button @click="dialogVisible = false">取 消</el-button> - </template> - </Dialog> + </el-form-item> + </el-form> </template> <script setup lang="ts"> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import * as LeaveApi from '@/api/bpm/leave' +import { useTagsViewStore } from '@/store/modules/tagsView' const message = useMessage() // 消息弹窗 +const { delView } = useTagsViewStore() // 视图操作 +const { currentRoute } = useRouter() // 路由 -const dialogVisible = ref(false) // 弹窗的是否展示 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formData = ref({ type: undefined, @@ -66,15 +65,7 @@ const formRules = reactive({ }) const formRef = ref() // 表单 Ref -/** 打开弹窗 */ -const open = async () => { - dialogVisible.value = true - resetForm() -} -defineExpose({ open }) // 提供 open 方法,用于打开弹窗 - /** 提交表单 */ -const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { // 校验表单 if (!formRef) return @@ -85,23 +76,11 @@ const submitForm = async () => { try { const data = formData.value as unknown as LeaveApi.LeaveVO await LeaveApi.createLeave(data) - message.success('新增成功') - dialogVisible.value = false - // 发送操作成功的事件 - emit('success') + message.success('发起成功') + // 关闭当前 Tab + delView(unref(currentRoute)) } finally { formLoading.value = false } } - -/** 重置表单 */ -const resetForm = () => { - formData.value = { - type: undefined, - reason: undefined, - startTime: undefined, - endTime: undefined - } - formRef.value?.resetFields() -} </script> diff --git a/src/views/bpm/oa/leave/detail.vue b/src/views/bpm/oa/leave/detail.vue index 838be149..2efc37fb 100644 --- a/src/views/bpm/oa/leave/detail.vue +++ b/src/views/bpm/oa/leave/detail.vue @@ -1,40 +1,48 @@ <template> - <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="200"> + <ContentWrap> <el-descriptions border :column="1"> <el-descriptions-item label="请假类型"> <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="detailData.type" /> </el-descriptions-item> <el-descriptions-item label="开始时间"> - {{ formatDate(detailData.startTime) }} + {{ formatDate(detailData.startTime, 'YYYY-MM-DD') }} </el-descriptions-item> <el-descriptions-item label="结束时间"> - {{ formatDate(detailData.endTime) }} + {{ formatDate(detailData.endTime, 'YYYY-MM-DD') }} </el-descriptions-item> <el-descriptions-item label="原因"> {{ detailData.reason }} </el-descriptions-item> </el-descriptions> - </Dialog> + </ContentWrap> </template> -<script setup lang="ts"> +<script setup lang="ts" name="OALeaveCreate"> import { DICT_TYPE } from '@/utils/dict' import { formatDate } from '@/utils/formatTime' +import { propTypes } from '@/utils/propTypes' import * as LeaveApi from '@/api/bpm/leave' +const { query } = useRoute() // 查询参数 -const dialogVisible = ref(false) // 弹窗的是否展示 +const props = defineProps({ + id: propTypes.number.def(undefined) +}) const detailLoading = ref(false) // 表单的加载中 -const detailData = ref() // 详情数据 +const detailData = ref({}) // 详情数据 +const queryId = query.id as unknown as number // 从 URL 传递过来的 id 编号 -/** 打开弹窗 */ -const open = async (data: LeaveApi.LeaveVO) => { - dialogVisible.value = true - // 设置数据 +/** 获得数据 */ +const getInfo = async () => { detailLoading.value = true try { - detailData.value = data + detailData.value = await LeaveApi.getLeave(queryId || props.id) } finally { detailLoading.value = false } } -defineExpose({ open }) // 提供 open 方法,用于打开弹窗 +defineExpose({ open: getInfo }) // 提供 open 方法,用于打开弹窗 + +/** 初始化 **/ +onMounted(() => { + getInfo() +}) </script> diff --git a/src/views/bpm/oa/leave/index.vue b/src/views/bpm/oa/leave/index.vue index ebf10d72..901b6038 100644 --- a/src/views/bpm/oa/leave/index.vue +++ b/src/views/bpm/oa/leave/index.vue @@ -137,19 +137,12 @@ @pagination="getList" /> </ContentWrap> - - <!-- 表单弹窗:详情 --> - <LeaveDetail ref="detailRef" /> - <!-- 表单弹窗:添加 --> - <LeaveForm ref="formRef" @success="getList" /> </template> <script setup lang="ts" name="BpmOALeave"> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import * as LeaveApi from '@/api/bpm/leave' import * as ProcessInstanceApi from '@/api/bpm/processInstance' -import LeaveDetail from './detail.vue' -import LeaveForm from './create.vue' const message = useMessage() // 消息弹窗 const router = useRouter() // 路由 const { t } = useI18n() // 国际化 @@ -192,15 +185,18 @@ const resetQuery = () => { } /** 添加操作 */ -const formRef = ref() const handleCreate = () => { - formRef.value.open() + router.push({ name: 'OALeaveCreate' }) } /** 详情操作 */ -const detailRef = ref() -const handleDetail = (data: LeaveApi.LeaveVO) => { - detailRef.value.open(data) +const handleDetail = (row: LeaveApi.LeaveVO) => { + router.push({ + name: 'OALeaveDetail', + query: { + id: row.id + } + }) } /** 取消请假操作 */ From abf9b50c2f9a4ceb19066b7e722336a7bff05759 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 16:37:11 +0800 Subject: [PATCH 13/15] =?UTF-8?q?REVIEW=20=E7=B4=A0=E6=9D=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=9A=84=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/mp/components/img.png | Bin 15404 -> 0 bytes .../{Waterfall.vue => ImageTable.vue} | 0 .../components/{Upload.vue => UploadFile.vue} | 3 -- .../mp/material/components/UploadVideo.vue | 2 - .../mp/material/components/VideoTable.vue | 2 - .../mp/material/components/VoiceTable.vue | 2 - src/views/mp/material/components/upload.ts | 16 ++++---- src/views/mp/material/index.vue | 37 +++++++----------- 8 files changed, 21 insertions(+), 41 deletions(-) delete mode 100644 src/views/mp/components/img.png rename src/views/mp/material/components/{Waterfall.vue => ImageTable.vue} (100%) rename src/views/mp/material/components/{Upload.vue => UploadFile.vue} (98%) diff --git a/src/views/mp/components/img.png b/src/views/mp/components/img.png deleted file mode 100644 index c25a6e762f3a84c5a7f05c6383de843937725fcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15404 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 D*J2vT diff --git a/src/views/mp/material/components/Waterfall.vue b/src/views/mp/material/components/ImageTable.vue similarity index 100% rename from src/views/mp/material/components/Waterfall.vue rename to src/views/mp/material/components/ImageTable.vue diff --git a/src/views/mp/material/components/Upload.vue b/src/views/mp/material/components/UploadFile.vue similarity index 98% rename from src/views/mp/material/components/Upload.vue rename to src/views/mp/material/components/UploadFile.vue index 541dbc20..3ab62224 100644 --- a/src/views/mp/material/components/Upload.vue +++ b/src/views/mp/material/components/UploadFile.vue @@ -20,7 +20,6 @@ </template> </el-upload> </template> - <script setup lang="ts"> import type { UploadProps, UploadUserFile } from 'element-plus' import { @@ -66,5 +65,3 @@ const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { emit('uploaded') } </script> - -<style scoped></style> diff --git a/src/views/mp/material/components/UploadVideo.vue b/src/views/mp/material/components/UploadVideo.vue index 5da7d980..816711d1 100644 --- a/src/views/mp/material/components/UploadVideo.vue +++ b/src/views/mp/material/components/UploadVideo.vue @@ -123,5 +123,3 @@ const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { emit('uploaded') } </script> - -<style scoped></style> diff --git a/src/views/mp/material/components/VideoTable.vue b/src/views/mp/material/components/VideoTable.vue index 3bd2fe00..81472959 100644 --- a/src/views/mp/material/components/VideoTable.vue +++ b/src/views/mp/material/components/VideoTable.vue @@ -57,5 +57,3 @@ const handleDownload = (url: string) => { window.open(url, '_blank') } </script> - -<style scoped></style> diff --git a/src/views/mp/material/components/VoiceTable.vue b/src/views/mp/material/components/VoiceTable.vue index 44bd01da..6f37e1a0 100644 --- a/src/views/mp/material/components/VoiceTable.vue +++ b/src/views/mp/material/components/VoiceTable.vue @@ -49,5 +49,3 @@ const emit = defineEmits<{ (e: 'delete', v: number) }>() </script> - -<style scoped></style> diff --git a/src/views/mp/material/components/upload.ts b/src/views/mp/material/components/upload.ts index 37441f5b..239665a2 100644 --- a/src/views/mp/material/components/upload.ts +++ b/src/views/mp/material/components/upload.ts @@ -1,10 +1,9 @@ import type { UploadProps, UploadRawFile } from 'element-plus' import { getAccessToken } from '@/utils/auth' - -const message = useMessage() - -const HEADERS = { Authorization: 'Bearer ' + getAccessToken() } -const UPLOAD_URL = 'http://127.0.0.1:8000/upload/' //import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' +const message = useMessage() // 消息 +const HEADERS = { Authorization: 'Bearer ' + getAccessToken() } // 请求头 +// const UPLOAD_URL = 'http://127.0.0.1:8000/upload/' // 上传地址 +const UPLOAD_URL = import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' // 上传地址 enum MaterialType { Image = 'image', @@ -22,7 +21,6 @@ const beforeUpload = (rawFile: UploadRawFile, materialType: MaterialType): boole let allowTypes: string[] = [] let maxSizeMB = 0 let name = '' - switch (materialType) { case MaterialType.Image: allowTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'] @@ -38,18 +36,18 @@ const beforeUpload = (rawFile: UploadRawFile, materialType: MaterialType): boole allowTypes = ['video/mp4'] maxSizeMB = 10 name = '视频' + break } - + // 格式不正确 if (!allowTypes.includes(rawFile.type)) { message.error(`上传${name}格式不对!`) return false } - + // 大小不正确 if (rawFile.size / 1024 / 1024 > maxSizeMB) { message.error(`上传${name}大小不能超过${maxSizeMB}M!`) return false } - return true } diff --git a/src/views/mp/material/index.vue b/src/views/mp/material/index.vue index dd54cf19..4d8d3707 100644 --- a/src/views/mp/material/index.vue +++ b/src/views/mp/material/index.vue @@ -16,14 +16,15 @@ <template #label> <span> <Icon icon="ep:picture" />图片 </span> </template> - <Upload + <UploadFile v-hasPermi="['mp:material:upload-permanent']" :type="MaterialType.Image" @uploaded="getList" > 支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M - </Upload> - <Waterfall :loading="loading" :list="list" @delete="handleDelete" /> + </UploadFile> + <!-- 列表 --> + <ImageTable :loading="loading" :list="list" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -38,14 +39,13 @@ <template #label> <span> <Icon icon="ep:microphone" />语音 </span> </template> - <Upload + <UploadFile v-hasPermi="['mp:material:upload-permanent']" :type="MaterialType.Voice" @uploaded="getList" > 格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s - </Upload> - + </UploadFile> <!-- 列表 --> <VoiceTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> @@ -71,7 +71,6 @@ > <!-- 新建视频的弹窗 --> <UploadVideo v-model="showCreateVideo" /> - <!-- 列表 --> <VideoTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> @@ -85,21 +84,18 @@ </el-tabs> </ContentWrap> </template> - <script lang="ts" setup name="MpMaterial"> import WxAccountSelect from '@/views/mp/components/wx-account-select/main.vue' -import Waterfall from './components/Waterfall.vue' +import ImageTable from './components/ImageTable.vue' import VoiceTable from './components/VoiceTable.vue' import VideoTable from './components/VideoTable.vue' -import Upload from './components/Upload.vue' +import UploadFile from './components/UploadFile.vue' import UploadVideo from './components/UploadVideo.vue' import { MaterialType } from './components/upload' import * as MpMaterialApi from '@/api/mp/material' +const message = useMessage() // 消息 -const message = useMessage() - -// 素材类型 -const type = ref<MaterialType>(MaterialType.Image) +const type = ref<MaterialType>(MaterialType.Image) // 素材类型 const loading = ref(false) // 遮罩层 const list = ref<any[]>([]) // 总条数 const total = ref(0) // 数据列表 @@ -116,9 +112,7 @@ const queryParams: QueryParams = reactive({ accountId: undefined, permanent: true }) - -// === 视频上传,独有变量 === -const showCreateVideo = ref(false) +const showCreateVideo = ref(false) // 是否新建视频的弹窗 /** 侦听公众号变化 **/ const onAccountChanged = (id?: number) => { @@ -126,7 +120,6 @@ const onAccountChanged = (id?: number) => { getList() } -// ======================== 列表查询 ======================== /** 查询列表 */ const getList = async () => { loading.value = true @@ -148,21 +141,19 @@ const handleQuery = () => { getList() } +/** 处理 table 切换 */ const onTabChange = () => { - // 提前情况数据,避免tab切换后显示垃圾数据 + // 提前情况数据,避免 tab 切换后显示垃圾数据 list.value = [] total.value = 0 - // 从第一页开始查询 handleQuery() } -// ======================== 其它操作 ======================== +/** 处理删除操作 */ const handleDelete = async (id: number) => { await message.confirm('此操作将永久删除该文件, 是否继续?') await MpMaterialApi.deletePermanentMaterial(id) message.alertSuccess('删除成功') } </script> - -<style lang="scss" scoped></style> From e3660e0b20f4515e1c524b079cfc8f6937e288ef Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 17:07:41 +0800 Subject: [PATCH 14/15] =?UTF-8?q?REVIEW=20=E7=AB=99=E5=86=85=E4=BF=A1?= =?UTF-8?q?=E6=A8=A1=E7=89=88=E7=9A=84=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/notify/template/index.ts | 23 ++-- .../notify/template/NotifyTemplateForm.vue | 13 +- .../template/NotifyTemplateSendForm.vue | 127 ++++++++++++++++++ src/views/system/notify/template/index.vue | 117 ++-------------- 4 files changed, 152 insertions(+), 128 deletions(-) create mode 100644 src/views/system/notify/template/NotifyTemplateSendForm.vue diff --git a/src/api/system/notify/template/index.ts b/src/api/system/notify/template/index.ts index f2bf5d27..50196e85 100644 --- a/src/api/system/notify/template/index.ts +++ b/src/api/system/notify/template/index.ts @@ -1,24 +1,17 @@ import request from '@/config/axios' export interface NotifyTemplateVO { - id: number | null + id?: number name: string nickname: string code: string content: string - type: number | null + type: number params: string - status: number | null + status: number remark: string } -export interface NotifyTemplatePageReqVO extends PageParam { - name?: string - code?: string - status?: number - createTime?: Date[] -} - export interface NotifySendReqVO { userId: number | null templateCode: string @@ -26,22 +19,22 @@ export interface NotifySendReqVO { } // 查询站内信模板列表 -export const getNotifyTemplatePageApi = async (params: NotifyTemplatePageReqVO) => { +export const getNotifyTemplatePage = async (params: PageParam) => { return await request.get({ url: '/system/notify-template/page', params }) } // 查询站内信模板详情 -export const getNotifyTemplateApi = async (id: number) => { +export const getNotifyTemplate = async (id: number) => { return await request.get({ url: '/system/notify-template/get?id=' + id }) } // 新增站内信模板 -export const createNotifyTemplateApi = async (data: NotifyTemplateVO) => { +export const createNotifyTemplate = async (data: NotifyTemplateVO) => { return await request.post({ url: '/system/notify-template/create', data }) } // 修改站内信模板 -export const updateNotifyTemplateApi = async (data: NotifyTemplateVO) => { +export const updateNotifyTemplate = async (data: NotifyTemplateVO) => { return await request.put({ url: '/system/notify-template/update', data }) } @@ -51,6 +44,6 @@ export const deleteNotifyTemplateApi = async (id: number) => { } // 发送站内信 -export const sendNotifyApi = (data: NotifySendReqVO) => { +export const sendNotify = (data: NotifySendReqVO) => { return request.post({ url: '/system/notify-template/send-notify', data }) } diff --git a/src/views/system/notify/template/NotifyTemplateForm.vue b/src/views/system/notify/template/NotifyTemplateForm.vue index d600a59c..55e51ebd 100644 --- a/src/views/system/notify/template/NotifyTemplateForm.vue +++ b/src/views/system/notify/template/NotifyTemplateForm.vue @@ -25,7 +25,7 @@ v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE)" :key="dict.value" :label="dict.label" - :value="parseInt(dict.value)" + :value="dict.value" /> </el-select> </el-form-item> @@ -34,7 +34,7 @@ <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" - :label="parseInt(dict.value as string)" + :label="dict.value as string" > {{ dict.label }} </el-radio> @@ -81,6 +81,7 @@ const formRules = reactive({ }) const formRef = ref() // 表单 Ref +/** 打开弹窗 */ const open = async (type: string, id?: number) => { dialogVisible.value = true dialogTitle.value = type @@ -90,7 +91,7 @@ const open = async (type: string, id?: number) => { if (id) { formLoading.value = true try { - formData.value = await NotifyTemplateApi.getNotifyTemplateApi(id) + formData.value = await NotifyTemplateApi.getNotifyTemplate(id) } finally { formLoading.value = false } @@ -107,12 +108,12 @@ const submitForm = async () => { if (!valid) return formLoading.value = true try { - const data = formData.value as NotifyTemplateApi.NotifyTemplateVO + const data = formData.value as unknown as NotifyTemplateApi.NotifyTemplateVO if (formType.value === 'create') { - await NotifyTemplateApi.createNotifyTemplateApi(data) + await NotifyTemplateApi.createNotifyTemplate(data) message.success('新增成功') } else { - await NotifyTemplateApi.updateNotifyTemplateApi(data) + await NotifyTemplateApi.updateNotifyTemplate(data) message.success('修改成功') } dialogVisible.value = false diff --git a/src/views/system/notify/template/NotifyTemplateSendForm.vue b/src/views/system/notify/template/NotifyTemplateSendForm.vue new file mode 100644 index 00000000..9e292a8d --- /dev/null +++ b/src/views/system/notify/template/NotifyTemplateSendForm.vue @@ -0,0 +1,127 @@ +<template> + <Dialog v-model="dialogVisible" title="测试发送" :max-height="500"> + <el-form + ref="formRef" + v-loading="formLoading" + :model="formData" + :rules="formRules" + label-width="140px" + > + <el-form-item label="模板内容" prop="content"> + <el-input + v-model="formData.content" + placeholder="请输入模板内容" + readonly + type="textarea" + /> + </el-form-item> + <el-form-item label="接收人" prop="userId"> + <el-select v-model="formData.userId" placeholder="请选择接收人"> + <el-option + v-for="item in userOption" + :key="item.id" + :label="item.nickname" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item + v-for="param in formData.params" + :key="param" + :label="'参数 {' + param + '}'" + :prop="'templateParams.' + param" + > + <el-input + v-model="formData.templateParams[param]" + :placeholder="'请输入 ' + param + ' 参数'" + /> + </el-form-item> + </el-form> + <template #footer> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> + <el-button @click="dialogVisible = false">取 消</el-button> + </template> + </Dialog> +</template> +<script lang="ts" name="SystemNotifyTemplateSendForm" setup> +import * as SmsTemplateApi from '@/api/system/sms/smsTemplate' +import * as UserApi from '@/api/system/user' +import * as NotifyTemplateApi from '@/api/system/notify/template' +const message = useMessage() // 消息弹窗 + +const dialogVisible = ref(false) // 弹窗的是否展示 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formData = ref({ + content: '', + params: {}, + userId: null, + templateCode: '', + templateParams: new Map() +}) +const formRules = reactive({ + userId: [{ required: true, message: '用户编号不能为空', trigger: 'change' }], + templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], + templateParams: {} +}) +const formRef = ref() // 表单 Ref +const userOption = ref<UserApi.UserVO[]>([]) + +const open = async (id: number) => { + dialogVisible.value = true + resetForm() + // 设置数据 + formLoading.value = true + try { + const data = await NotifyTemplateApi.getNotifyTemplate(id) + // 设置动态表单 + formData.value.content = data.content + formData.value.params = data.params + formData.value.templateCode = data.code + formData.value.templateParams = data.params.reduce((obj, item) => { + obj[item] = '' // 给每个动态属性赋值,避免无法读取 + return obj + }, {}) + formRules.templateParams = data.params.reduce((obj, item) => { + obj[item] = { required: true, message: '参数 ' + item + ' 不能为空', trigger: 'blur' } + return obj + }, {}) + } finally { + formLoading.value = false + } + // 加载用户列表 + userOption.value = await UserApi.getSimpleUserList() +} +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 提交表单 */ +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as SmsTemplateApi.SendSmsReqVO + const logId = await SmsTemplateApi.sendSms(data) + if (logId) { + message.success('提交发送成功!发送结果,见发送日志编号:' + logId) + } + dialogVisible.value = false + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + content: '', + params: {}, + mobile: '', + templateCode: '', + templateParams: new Map() + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/system/notify/template/index.vue b/src/views/system/notify/template/index.vue index 9d37befb..6d1938ad 100644 --- a/src/views/system/notify/template/index.vue +++ b/src/views/system/notify/template/index.vue @@ -1,8 +1,8 @@ <template> <doc-alert title="站内信配置" url="https://doc.iocoder.cn/notify/" /> + <!-- 搜索工作栏 --> <ContentWrap> - <!-- 搜索工作栏 --> <el-form class="-mb-15px" :model="queryParams" @@ -99,7 +99,6 @@ width="200" :show-overflow-tooltip="true" /> - <el-table-column label="开启状态" align="center" prop="status" width="80"> <template #default="scope"> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> @@ -151,67 +150,22 @@ /> </ContentWrap> - <Dialog v-model="dialogFormVisible" title="测试发送" :max-height="500"> - <el-form - ref="sendFormRef" - :model="sendFormData" - :rules="sendFormRules" - label-width="140px" - v-loading="formLoading" - > - <el-form-item label="模板内容" prop="content"> - <el-input v-model="sendFormData.content" readonly /> - </el-form-item> - <el-form-item label="接收人" prop="userId"> - <el-select v-model="sendFormData.userId" placeholder="请选择接收人"> - <el-option - v-for="item in userOption" - :key="item.id" - :label="item.nickname" - :value="item.id" - /> - </el-select> - </el-form-item> - <el-form-item - v-for="param in sendFormData.params" - :key="param" - :label="'参数 {' + param + '}'" - :prop="'templateParams.' + param" - > - <el-input - v-model="sendFormData.templateParams[param]" - :placeholder="'请输入 ' + param + ' 参数'" - /> - </el-form-item> - </el-form> - <template #footer> - <span class="dialog-footer"> - <el-button @click="dialogFormVisible = false">取消</el-button> - <el-button type="primary" @click="submitForm"> 确定 </el-button> - </span> - </template> - </Dialog> - <!-- 表单弹窗:添加/修改 --> <NotifyTemplateForm ref="formRef" @success="getList" /> + <!-- 表单弹窗:测试发送 --> + <NotifyTemplateSendForm ref="sendFormRef" /> </template> <script setup lang="ts" name="NotifySmsTemplate"> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import * as NotifyTemplateApi from '@/api/system/notify/template' -import { getSimpleUserList, UserVO } from '@/api/system/user' import NotifyTemplateForm from './NotifyTemplateForm.vue' - +import NotifyTemplateSendForm from './NotifyTemplateSendForm.vue' const message = useMessage() // 消息弹窗 const loading = ref(false) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 -const queryFormRef = ref() // 搜索的表单 - -const formLoading = ref(false) -const dialogFormVisible = ref(false) -const sendFormRef = ref() // 表单 Ref const queryParams = reactive({ pageNo: 1, pageSize: 10, @@ -220,28 +174,13 @@ const queryParams = reactive({ code: undefined, createTime: [] }) - -const sendFormData = ref({ - content: '', - params: {}, - userId: null, - templateCode: '', - templateParams: {} -}) - -const sendFormRules = ref({ - userId: [{ required: true, message: '用户编号不能为空', trigger: 'change' }], - templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], - templateParams: {} -}) - -const userOption = ref<UserVO[]>([]) +const queryFormRef = ref() // 搜索的表单 /** 查询列表 */ const getList = async () => { loading.value = true try { - const data = await NotifyTemplateApi.getNotifyTemplatePageApi(queryParams) + const data = await NotifyTemplateApi.getNotifyTemplatePage(queryParams) list.value = data.list total.value = data.total } finally { @@ -280,50 +219,14 @@ const handleDelete = async (id: number) => { } catch {} } -const openSendForm = (row: any) => { - sendFormData.value.content = row.content - sendFormData.value.params = row.params - sendFormData.value.templateCode = row.code - sendFormData.value.templateParams = row.params.reduce(function (obj, item) { - obj[item] = undefined - return obj - }, {}) - sendFormRules.value.templateParams = row.params.reduce(function (obj, item) { - obj[item] = { required: true, message: '参数 ' + item + ' 不能为空', trigger: 'change' } - return obj - }, {}) - dialogFormVisible.value = true -} - -/** 提交表单 */ -const submitForm = async () => { - // 校验表单 - if (!sendFormRef) return - const valid = await sendFormRef.value.validate() - if (!valid) return - // 提交请求 - formLoading.value = true - try { - const data: NotifyTemplateApi.NotifySendReqVO = { - userId: sendFormData.value.userId, - templateCode: sendFormData.value.templateCode, - templateParams: sendFormData.value.templateParams as unknown as Map<string, Object> - } - const res = await NotifyTemplateApi.sendNotifyApi(data) - if (res) { - message.success('提交发送成功!发送结果,见消息记录编号:' + res) - } - dialogFormVisible.value = false - } finally { - formLoading.value = false - } +/** 发送站内信按钮 */ +const sendFormRef = ref() // 表单 Ref +const openSendForm = (row: NotifyTemplateApi.NotifyTemplateVO) => { + sendFormRef.value.open(row.id) } /** 初始化 **/ onMounted(() => { getList() - getSimpleUserList().then((data) => { - userOption.value = data - }) }) </script> From 06974ca3c084715d31d36341c230f342cb0ea143 Mon Sep 17 00:00:00 2001 From: YunaiV <zhijiantianya@gmail.com> Date: Sat, 15 Apr 2023 17:28:33 +0800 Subject: [PATCH 15/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=89=93=E5=8C=85?= =?UTF-8?q?=E4=BC=9A=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/mp/components/wx-editor/WxEditor.vue | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/views/mp/components/wx-editor/WxEditor.vue diff --git a/src/views/mp/components/wx-editor/WxEditor.vue b/src/views/mp/components/wx-editor/WxEditor.vue deleted file mode 100644 index e69de29b..00000000