问题修复

This commit is contained in:
ktianc 2023-04-05 21:30:04 +08:00
parent 2ba2738107
commit 16069f0ae0
7 changed files with 452 additions and 1 deletions

View File

@ -0,0 +1,96 @@
<script setup lang="ts">
import { ElButton, ElTable, ElTableColumn, ElPopconfirm, ElMessage, ElTag } from 'element-plus'
import { postUsersInitPasswordSendEmailApi } from '@/api/vadmin/auth/user'
import { ref, PropType } from 'vue'
const props = defineProps({
selections: {
type: Object as PropType<Recordable[]>
}
})
const tableData = ref(JSON.parse(JSON.stringify(props.selections)))
const loading = ref(false)
const handleDelete = (index: number) => {
tableData.value.splice(index, 1)
}
const initPassword = async () => {
loading.value = true
const ids = tableData.value
.filter((item) => item.reset_password_status !== true)
.map((item) => item.id)
if (ids.length <= 0) {
return ElMessage.warning('已全部重置完成,无需重复操作')
}
const res = await postUsersInitPasswordSendEmailApi(ids).finally(() => {
loading.value = false
})
if (res) {
tableData.value = res.data
ElMessage.success('重置成功')
}
}
</script>
<template>
<div>
<div class="flex justify-between">
<span>已选用户列表</span>
<ElButton
type="primary"
:disabled="tableData?.length === 0"
:loading="loading"
@click="initPassword"
>确认重置并发送邮件通知</ElButton
>
</div>
<ElTable
:data="tableData"
:stripe="true"
:border="true"
style="width: 100%"
class="mt-10px"
max-height="500px"
>
<ElTableColumn prop="id" label="用户编号" width="100" align="center" />
<ElTableColumn prop="name" label="姓名" width="120" align="center" />
<ElTableColumn prop="email" label="邮箱" width="200" align="center" />
<ElTableColumn prop="reset_password_status" label="重置状态" width="100" align="center">
<template #default="scope">
<ElTag v-if="scope.row.reset_password_status === true" type="success" effect="dark">
重置成功
</ElTag>
<ElTag v-else-if="scope.row.reset_password_status === false" type="danger" effect="dark">
重置失败
</ElTag>
<ElTag v-else type="warning" effect="dark"> 待重置 </ElTag>
</template>
</ElTableColumn>
<ElTableColumn prop="send_sms_status" label="发送状态" width="100" align="center">
<template #default="scope">
<ElTag v-if="scope.row.send_sms_status === true" type="success" effect="dark">
发送成功
</ElTag>
<ElTag v-else-if="scope.row.send_sms_status === false" type="danger" effect="dark">
发送失败
</ElTag>
<ElTag v-else type="warning" effect="dark"> 待发送 </ElTag>
</template>
</ElTableColumn>
<ElTableColumn prop="send_sms_msg" label="描述" align="center" />
<ElTableColumn fixed="right" label="操作" width="100" align="center">
<template #default="scope">
<ElPopconfirm title="确认移除吗?" @confirm="handleDelete(scope.$index)">
<template #reference>
<ElButton v-if="scope.row.send_sms_status !== true" link type="primary" size="small"
>移除</ElButton
>
</template>
</ElPopconfirm>
</template>
</ElTableColumn>
</ElTable>
</div>
</template>

View File

@ -0,0 +1,96 @@
<script setup lang="ts">
import { ElButton, ElTable, ElTableColumn, ElPopconfirm, ElMessage, ElTag } from 'element-plus'
import { postUsersInitPasswordSendSMSApi } from '@/api/vadmin/auth/user'
import { ref, PropType } from 'vue'
const props = defineProps({
selections: {
type: Object as PropType<Recordable[]>
}
})
const tableData = ref(JSON.parse(JSON.stringify(props.selections)))
const loading = ref(false)
const handleDelete = (index: number) => {
tableData.value.splice(index, 1)
}
const initPassword = async () => {
loading.value = true
const ids = tableData.value
.filter((item) => item.reset_password_status !== true)
.map((item) => item.id)
if (ids.length <= 0) {
return ElMessage.warning('已全部重置完成,无需重复操作')
}
const res = await postUsersInitPasswordSendSMSApi(ids).finally(() => {
loading.value = false
})
if (res) {
tableData.value = res.data
ElMessage.success('重置成功')
}
}
</script>
<template>
<div>
<div class="flex justify-between">
<span>已选用户列表</span>
<ElButton
type="primary"
:disabled="tableData?.length === 0"
:loading="loading"
@click="initPassword"
>确认重置并发送短信通知</ElButton
>
</div>
<ElTable
:data="tableData"
:stripe="true"
:border="true"
style="width: 100%"
class="mt-10px"
max-height="500px"
>
<ElTableColumn prop="id" label="用户编号" width="100" align="center" />
<ElTableColumn prop="name" label="姓名" width="120" align="center" />
<ElTableColumn prop="telephone" label="手机号" width="120" align="center" />
<ElTableColumn prop="reset_password_status" label="重置状态" width="100" align="center">
<template #default="scope">
<ElTag v-if="scope.row.reset_password_status === true" type="success" effect="dark">
重置成功
</ElTag>
<ElTag v-else-if="scope.row.reset_password_status === false" type="danger" effect="dark">
重置失败
</ElTag>
<ElTag v-else type="warning" effect="dark"> 待重置 </ElTag>
</template>
</ElTableColumn>
<ElTableColumn prop="send_sms_status" label="发送状态" width="100" align="center">
<template #default="scope">
<ElTag v-if="scope.row.send_sms_status === true" type="success" effect="dark">
发送成功
</ElTag>
<ElTag v-else-if="scope.row.send_sms_status === false" type="danger" effect="dark">
发送失败
</ElTag>
<ElTag v-else type="warning" effect="dark"> 待发送 </ElTag>
</template>
</ElTableColumn>
<ElTableColumn prop="send_sms_msg" label="描述" align="center" />
<ElTableColumn fixed="right" label="操作" width="100" align="center">
<template #default="scope">
<ElPopconfirm title="确认移除吗?" @confirm="handleDelete(scope.$index)">
<template #reference>
<ElButton v-if="scope.row.send_sms_status !== true" link type="primary" size="small"
>移除</ElButton
>
</template>
</ElPopconfirm>
</template>
</ElTableColumn>
</ElTable>
</div>
</template>

View File

@ -0,0 +1,64 @@
import { FormSchema } from '@/types/form'
import { reactive } from 'vue'
export const schema = reactive<FormSchema[]>([
{
field: 'email_access',
label: '邮箱账号',
colProps: {
span: 24
},
component: 'Input',
componentProps: {
style: {
width: '500px'
}
}
},
{
field: 'email_password',
label: '邮箱密码',
colProps: {
span: 24
},
component: 'Input',
componentProps: {
style: {
width: '500px'
}
}
},
{
field: 'email_server',
label: '邮箱服务器',
colProps: {
span: 24
},
component: 'Input',
componentProps: {
style: {
width: '500px'
}
}
},
{
field: 'email_port',
label: '服务器端口',
colProps: {
span: 24
},
component: 'Input',
componentProps: {
style: {
width: '500px'
}
}
},
{
field: 'active',
label: '',
colProps: {
span: 24
}
}
])

View File

@ -0,0 +1,64 @@
<script setup lang="ts">
import { Form } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { schema } from './components/email.data'
import { ElButton } from 'element-plus'
import { getSystemSettingsApi, putSystemSettingsApi } from '@/api/vadmin/system/settings'
import { ref, unref } from 'vue'
import { ElMessage } from 'element-plus'
import { propTypes } from '@/utils/propTypes'
const props = defineProps({
tabId: propTypes.number
})
const { register, methods, elFormRef } = useForm({
schema: schema
})
const { setValues } = methods
let formData = ref({} as Recordable)
const getData = async () => {
const res = await getSystemSettingsApi({ tab_id: props.tabId })
if (res) {
setValues(res.data)
formData.value = res.data
}
}
const loading = ref(false)
const save = async () => {
const formRef = unref(elFormRef)
await formRef?.validate(async (isValid) => {
if (isValid) {
loading.value = true
let data = await methods.getFormData()
if (!data) {
loading.value = false
return ElMessage.error('未获取到数据')
}
const res = await putSystemSettingsApi(data)
if (res) {
getData()
return ElMessage.success('更新成功')
}
loading.value = false
}
})
}
getData()
</script>
<template>
<Form @register="register">
<template #active>
<ElButton type="primary" @click="save">立即提交</ElButton>
</template>
</Form>
</template>
<style scoped lang="less"></style>

View File

@ -96,7 +96,7 @@ def migrate(env: Environment = Environment.pro):
:params name: 数据库环境
"""
print("开始更新数据库表")
InitializeData().migrate_model(env)
InitializeData.migrate_model(env)
@shell_app.command()

40
kinit-api/utils/count.py Normal file
View File

@ -0,0 +1,40 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Creaet Time : 2022/11/3 17:23
# @File : count.py
# @IDE : PyCharm
# @desc : 计数
from aioredis.client import Redis
class Count:
"""
计数
"""
def __init__(self, rd: Redis, key):
self.rd = rd
self.key = key
async def add(self, ex: int = None) -> int:
await self.rd.set(self.key, await self.get_count() + 1, ex=ex)
return await self.get_count()
async def subtract(self, ex: int = None) -> int:
await self.rd.set(self.key, await self.get_count() - 1, ex=ex)
return await self.get_count()
async def get_count(self) -> int:
number = await self.rd.get(self.key)
if number:
return int(number)
return 0
async def reset(self) -> None:
await self.rd.set(self.key, 0)
async def delete(self) -> None:
await self.rd.delete(self.key)

View File

@ -0,0 +1,91 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Creaet Time : 2023/3/27 9:48
# @File : send_email.py
# @IDE : PyCharm
# @desc : 发送邮件封装类
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from typing import List
from aioredis import Redis
from core.exception import CustomException
from utils.cache import Cache
class EmailSender:
def __init__(self, rd: Redis):
self.email = None
self.password = None
self.smtp_server = None
self.smtp_port = None
self.server = None
self.rd = rd
async def __get_settings(self, retry: int = 3):
"""
获取配置信息
"""
web_email = await Cache(self.rd).get_tab_name("web_email", retry)
self.email = web_email.get("email_access")
self.password = web_email.get("email_password")
self.smtp_server = web_email.get("email_server")
self.smtp_port = int(web_email.get("email_port"))
self.server = smtplib.SMTP(self.smtp_server, self.smtp_port)
self.server.starttls()
try:
self.server.login(self.email, self.password)
except smtplib.SMTPAuthenticationError:
raise CustomException("邮箱服务器认证失败!")
async def send_email(self, to_emails: List[str], subject: str, body: str, attachments: List[str] = None):
"""
发送邮件
:param to_emails: 收件人一个或多个
:param subject: 主题
:param body: 内容
:param attachments: 附件
"""
await self.__get_settings()
message = MIMEMultipart()
message['From'] = self.email
message['To'] = ', '.join(to_emails)
message['Subject'] = subject
body = MIMEText(body)
message.attach(body)
if attachments:
for attachment in attachments:
with open(attachment, 'rb') as f:
file_data = f.read()
filename = attachment.split('/')[-1]
attachment = MIMEApplication(file_data, Name=filename)
attachment['Content-Disposition'] = f'attachment; filename="{filename}"'
message.attach(attachment)
try:
result = self.server.sendmail(self.email, to_emails, message.as_string())
self.server.quit()
print("邮件发送结果", result)
if result:
return False
else:
return True
except smtplib.SMTPException as e:
self.server.quit()
print('邮件发送失败!错误信息:', e)
return False
# if __name__ == '__main__':
# sender = EmailSender()
# to_emails = ['ktianc2001@163.com', '2445667550@qq.com']
# subject = 'Test email'
# body = 'This is a test email'
# sender.send_email(to_emails, subject, body)