u
This commit is contained in:
1 parent
68f08d921a
commit
3656d05f62
97 files changed
+17495
No files matched your search
@@ -0,0 +1,162 @@
|
||||
<script setup lang="ts">
|
||||
import type { UploadFile, UploadFileItem } from 'sard-uniapp'
|
||||
import { dialog, isImageUrl, isVideoUrl, toast } from 'sard-uniapp'
|
||||
import { aliyunpluploadApi, delSubRecordApi, loaddataAttachApi } from '@/request/api'
|
||||
import { downloadFile, formatFileSize, imageCompress, isImage, uploadFileToAliyun } from '@/utils/file'
|
||||
|
||||
const fileList = ref<UploadFileItem[]>([])
|
||||
|
||||
const isEdit = ref(true)
|
||||
|
||||
const aliyunBucket = import.meta.env.VITE_ALIYUN_BUCKET
|
||||
const father = ref('')
|
||||
const moduleid = ref('')
|
||||
const cateid = ref('')
|
||||
|
||||
onLoad((options) => {
|
||||
father.value = options.father
|
||||
moduleid.value = options.moduleid
|
||||
cateid.value = options.cateid || ''
|
||||
|
||||
const edit = options.edit || '0'
|
||||
isEdit.value = edit === '1'
|
||||
|
||||
nextTick(() => {
|
||||
loadFileData()
|
||||
})
|
||||
})
|
||||
|
||||
async function loadFileData() {
|
||||
let searchcondition = ` father = '${father.value}' and mx_moduleid = '${moduleid.value}'`
|
||||
if (cateid.value !== '') {
|
||||
searchcondition += ` and mx_cate_id = '${cateid.value}'`
|
||||
}
|
||||
loaddataAttachApi({
|
||||
viewname: 'bf_files',
|
||||
searchcondition,
|
||||
orderfield: 'mx_xh',
|
||||
soption: '',
|
||||
}).then((res) => {
|
||||
fileList.value = res.data.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
name: item.mx_filename,
|
||||
url: item.mx_mapfilename,
|
||||
}
|
||||
})
|
||||
|
||||
console.log(fileList.value)
|
||||
})
|
||||
}
|
||||
|
||||
function onItemClick(fileItem: UploadFileItem) {
|
||||
console.log(fileItem)
|
||||
if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) {
|
||||
downloadFile(fileItem.mx_mapfilename, fileItem.name)
|
||||
}
|
||||
}
|
||||
|
||||
function beforeRead(file: UploadFile): boolean | Promise<UploadFile> {
|
||||
// 非图片直接允许上传
|
||||
if (!isImage(file.name))
|
||||
return true
|
||||
|
||||
// 图片异步压缩,返回修改后的 UploadFile 对象
|
||||
return imageCompress(file.path).then((res) => {
|
||||
console.log(res)
|
||||
|
||||
file.path = res.path
|
||||
file.size = res.size
|
||||
return file
|
||||
}).catch((err) => {
|
||||
console.error('图片压缩失败:', err)
|
||||
return file
|
||||
})
|
||||
}
|
||||
|
||||
async function afterRead(fileItem: UploadFileItem) {
|
||||
try {
|
||||
// 设置上传中状态
|
||||
fileItem.status = 'uploading'
|
||||
fileItem.message = '正在上传'
|
||||
fileList.value = [...fileList.value]
|
||||
|
||||
// 上传到阿里云
|
||||
const res = await uploadFileToAliyun(
|
||||
fileItem.file.path,
|
||||
fileItem.file.name,
|
||||
fileItem.file.type,
|
||||
)
|
||||
|
||||
if (!res.url)
|
||||
throw new Error('上传失败:未获取到文件 URL')
|
||||
|
||||
// 调用后端接口保存文件信息
|
||||
const saveRes = await aliyunpluploadApi({
|
||||
despathfile: res.url,
|
||||
myfilename: fileItem.file.name,
|
||||
size: formatFileSize(fileItem.file.size),
|
||||
tablename: 'bf_files',
|
||||
sid: father.value,
|
||||
mx_moduleid: moduleid.value,
|
||||
mx_cate_id: cateid.value,
|
||||
})
|
||||
|
||||
if (saveRes.data === 'OK') {
|
||||
// 上传完成
|
||||
fileItem.status = 'done'
|
||||
fileItem.message = '上传成功'
|
||||
}
|
||||
else {
|
||||
// 后端返回非 OK
|
||||
throw new Error(saveRes.data || '上传失败')
|
||||
}
|
||||
|
||||
fileList.value = [...fileList.value]
|
||||
|
||||
loadFileData()
|
||||
}
|
||||
catch (err: any) {
|
||||
console.error('上传失败:', err)
|
||||
fileItem.status = 'failed'
|
||||
fileItem.message = err.message || '上传失败'
|
||||
fileList.value = [...fileList.value]
|
||||
}
|
||||
}
|
||||
function beforeRemove(index: number, fileItem: UploadFileItem): boolean | Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
dialog.confirm({
|
||||
title: '提示',
|
||||
message: `确定删除该张图片吗?`,
|
||||
onConfirm: () => resolve(),
|
||||
onCancel: () => reject(),
|
||||
onClose: () => reject(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onRemove(index: number, item: UploadFileItem) {
|
||||
delSubRecordApi({
|
||||
module: 'bf_files',
|
||||
id: item.subid,
|
||||
bucketName: aliyunBucket,
|
||||
}).then((res) => {
|
||||
if (res.data.result) {
|
||||
toast.success('删除成功')
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="file">
|
||||
<sar-result v-if="fileList.length === 0 && !isEdit" status="info" title="提示" description="暂无附件" />
|
||||
<sar-upload v-model="fileList" :readonly="!isEdit" :after-read="afterRead" :before-read="beforeRead" :before-remove="beforeRemove" multiple @item-click="onItemClick" @remove="onRemove" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file {
|
||||
padding: 36rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,253 @@
|
||||
<script lang="ts" setup>
|
||||
import type { FieldValidateError, FormExpose, FormRules } from 'sard-uniapp'
|
||||
import { getWindowInfo, toast } from 'sard-uniapp'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { loaddataApi, loginApi } from '@/request/api'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const startOffset = ref(getWindowInfo().statusBarHeight + 60)
|
||||
|
||||
const _loading = ref(false)
|
||||
|
||||
const formModel = reactive({
|
||||
orgid: userStore.userInfo.orgid,
|
||||
userid: userStore.userInfo.userid,
|
||||
password: '',
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
orgid: {
|
||||
required: true,
|
||||
message: '请输入机构码',
|
||||
},
|
||||
userid: {
|
||||
required: true,
|
||||
message: '请输入账号',
|
||||
},
|
||||
}
|
||||
|
||||
const formRef = ref<FormExpose>()
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
|
||||
_loading.value = true
|
||||
|
||||
const res = await loginApi({
|
||||
orgid: formModel.orgid,
|
||||
userid: formModel.userid,
|
||||
password: formModel.password,
|
||||
})
|
||||
|
||||
if (!res?.data) {
|
||||
toast.fail('登录失败,请检查账号密码')
|
||||
return
|
||||
}
|
||||
|
||||
userStore.userInfo = {
|
||||
...userStore.userInfo,
|
||||
orgid: formModel.orgid,
|
||||
userid: formModel.userid,
|
||||
token: res.data,
|
||||
}
|
||||
|
||||
let username = ''
|
||||
try {
|
||||
const userRes = await loaddataApi({
|
||||
viewname: 'v_b_truck',
|
||||
soption: '',
|
||||
orderfield: '',
|
||||
searchcondition: `b_id = '${formModel.userid}'`,
|
||||
})
|
||||
if (userRes?.data?.length > 0) {
|
||||
username = userRes.data[0].v_worker_name || ''
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.warn('获取用户信息失败', err)
|
||||
}
|
||||
|
||||
userStore.userInfo = {
|
||||
...userStore.userInfo,
|
||||
username,
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
})
|
||||
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index',
|
||||
})
|
||||
}
|
||||
catch (err: any) {
|
||||
// 表单验证错误
|
||||
if (Array.isArray(err)) {
|
||||
toast.fail(err[0].message)
|
||||
}
|
||||
else {
|
||||
console.error(err)
|
||||
toast.fail(err.message || '登录异常')
|
||||
}
|
||||
}
|
||||
finally {
|
||||
_loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="form-container">
|
||||
<sar-form-plain
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
:rules="formRules"
|
||||
scroll-to-first-error
|
||||
:scroll-into-view-options="{
|
||||
startOffset,
|
||||
position: 'start',
|
||||
}"
|
||||
>
|
||||
<view class="form-description">
|
||||
<view class="form-title">
|
||||
欢迎登录
|
||||
</view>
|
||||
<view class="form-subtitle">
|
||||
请输入机构码、账号和密码
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-list">
|
||||
<sar-form-item-plain name="orgid">
|
||||
<view class="form-label">
|
||||
<text>机构码</text>
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.orgid"
|
||||
placeholder="请输入机构码"
|
||||
clearable
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="company" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="userid">
|
||||
<view class="form-label">
|
||||
账号
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.userid"
|
||||
placeholder="请输入账号"
|
||||
clearable
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="user" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="password">
|
||||
<view class="form-label">
|
||||
密码
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.password"
|
||||
placeholder="请输入密码"
|
||||
type="password"
|
||||
clearable
|
||||
show-eye
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="lock" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
</view>
|
||||
|
||||
<view class="footer">
|
||||
<sar-button loading-type="clock" :loading="_loading" @click="onSubmit">
|
||||
登录
|
||||
</sar-button>
|
||||
</view>
|
||||
</sar-form-plain>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/style/mixins.scss';
|
||||
|
||||
.form-container {
|
||||
padding: 0rpx 32rpx;
|
||||
}
|
||||
|
||||
.form-description {
|
||||
padding: 64rpx 0 64rpx;
|
||||
color: var(--sar-secondary-color);
|
||||
|
||||
.form-title {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
.form-subtitle {
|
||||
margin-top: 16rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include flexGap(36rpx, column);
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.form-star {
|
||||
color: var(--sar-danger);
|
||||
}
|
||||
.form-input {
|
||||
margin-top: 20rpx;
|
||||
:deep(.sar-input) {
|
||||
background-color: #fff;
|
||||
.sar-icon {
|
||||
color: var(--sar-input-placeholder-color);
|
||||
}
|
||||
}
|
||||
:deep(.sar-input_focused) {
|
||||
.sar-input__prepend {
|
||||
.sar-icon {
|
||||
color: var(--sar-input-focused-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
// position: sticky;
|
||||
// bottom: 0;
|
||||
padding-top: 64rpx;
|
||||
:deep(.sar-button) {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,253 @@
|
||||
<script lang="ts" setup>
|
||||
import type { FieldValidateError, FormExpose, FormRules } from 'sard-uniapp'
|
||||
import { getWindowInfo, toast } from 'sard-uniapp'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { loaddataApi, saveobjtApi } from '@/request/api'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const startOffset = ref(getWindowInfo().statusBarHeight + 60)
|
||||
|
||||
const submitLoading = ref(false)
|
||||
|
||||
const formModel = reactive({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
}
|
||||
|
||||
const formRef = ref<FormExpose>()
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
await formRef.value?.validate()
|
||||
|
||||
if (formModel.confirmPassword !== formModel.newPassword) {
|
||||
toast.fail('两次输入的密码不一致,请重新输入')
|
||||
return
|
||||
}
|
||||
|
||||
submitLoading.value = true
|
||||
|
||||
const searchcondition = `b_id = '${userStore.userInfo.userid}' AND ISNULL(b_password, '') = ISNULL('${formModel.oldPassword}', '')`
|
||||
|
||||
const searchRes = await loaddataApi({
|
||||
viewname: 'v_mini_loginid',
|
||||
searchcondition: `${searchcondition}`,
|
||||
orderfield: 'b_id',
|
||||
soption: '',
|
||||
})
|
||||
|
||||
if (!searchRes.data || searchRes.data.length === 0) {
|
||||
toast.fail('旧密码错误,请重新输入')
|
||||
return
|
||||
}
|
||||
|
||||
const updateObj = {
|
||||
b_id: userStore.userInfo.userid,
|
||||
b_password: formModel.newPassword,
|
||||
}
|
||||
|
||||
const tables = []
|
||||
const insertValues = []
|
||||
const updateValues = []
|
||||
const delValues = []
|
||||
const keys = []
|
||||
|
||||
tables.push('b_truck')
|
||||
insertValues.push('[]')
|
||||
updateValues.push(JSON.stringify([updateObj]))
|
||||
delValues.push('[]')
|
||||
keys.push('b_id')
|
||||
|
||||
const saveobjtRes = await saveobjtApi({
|
||||
tables,
|
||||
insertValues,
|
||||
delValues,
|
||||
updateValues,
|
||||
keys,
|
||||
})
|
||||
|
||||
if (saveobjtRes.data === 'OK') {
|
||||
toast.success('密码修改成功,请重新登录')
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: '/pages-sub/login/index',
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
else {
|
||||
console.log(saveobjtRes)
|
||||
toast.fail(saveobjtRes.data || '修改失败')
|
||||
}
|
||||
}
|
||||
catch (error: any) {
|
||||
// 表单校验错误
|
||||
if (Array.isArray(error) && error[0]?.message) {
|
||||
toast.fail(error[0].message)
|
||||
}
|
||||
else {
|
||||
toast.fail('操作失败,请重试')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// 关闭 loading
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="form-container">
|
||||
<sar-form-plain
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
:rules="formRules"
|
||||
scroll-to-first-error
|
||||
:scroll-into-view-options="{
|
||||
startOffset,
|
||||
position: 'start',
|
||||
}"
|
||||
>
|
||||
<view class="form-description">
|
||||
<view class="form-title">
|
||||
密码修改
|
||||
</view>
|
||||
<view class="form-subtitle">
|
||||
确保账户安全,请谨慎操作
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-list">
|
||||
<sar-form-item-plain name="password">
|
||||
<view class="form-label">
|
||||
旧密码
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.oldPassword"
|
||||
placeholder="请输入旧密码"
|
||||
type="password"
|
||||
show-eye
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="lock" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="password">
|
||||
<view class="form-label">
|
||||
新密码
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.newPassword"
|
||||
placeholder="请输入新密码"
|
||||
type="password"
|
||||
show-eye
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="lock" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="password">
|
||||
<view class="form-label">
|
||||
确认密码
|
||||
</view>
|
||||
<view class="form-input">
|
||||
<sar-input
|
||||
v-model="formModel.confirmPassword"
|
||||
placeholder="请输入确认密码"
|
||||
type="password"
|
||||
show-eye
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="iconfont" name="lock" size="36rpx" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</view>
|
||||
</sar-form-item-plain>
|
||||
</view>
|
||||
|
||||
<view class="footer">
|
||||
<sar-button loading-type="clock" :loading="submitLoading" @click="onSubmit">
|
||||
确认修改
|
||||
</sar-button>
|
||||
</view>
|
||||
</sar-form-plain>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/style/mixins.scss';
|
||||
|
||||
.form-container {
|
||||
padding: 0rpx 32rpx;
|
||||
}
|
||||
|
||||
.form-description {
|
||||
padding: 64rpx 0 64rpx;
|
||||
color: var(--sar-secondary-color);
|
||||
|
||||
.form-title {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
.form-subtitle {
|
||||
margin-top: 16rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include flexGap(36rpx, column);
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.form-star {
|
||||
color: var(--sar-danger);
|
||||
}
|
||||
.form-input {
|
||||
margin-top: 20rpx;
|
||||
:deep(.sar-input) {
|
||||
background-color: #fff;
|
||||
.sar-icon {
|
||||
color: var(--sar-input-placeholder-color);
|
||||
}
|
||||
}
|
||||
:deep(.sar-input_focused) {
|
||||
.sar-input__prepend {
|
||||
.sar-icon {
|
||||
color: var(--sar-input-focused-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
// position: sticky;
|
||||
// bottom: 0;
|
||||
padding-top: 64rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user