u
This commit is contained in:
1 parent
1806808d11
commit
349db76d3d
19 files changed
+1328
-205
No files matched your search
+4
@@ -0,0 +1,4 @@
|
||||
VITE_APP_PORT = 8080
|
||||
|
||||
VITE_ALIYUN_BUCKET = 'g3xc'
|
||||
|
||||
@@ -8,7 +8,7 @@ onLaunch(() => {
|
||||
console.log('App Launch')
|
||||
})
|
||||
onShow(() => {
|
||||
// userStore.requireLogin()
|
||||
userStore.requireLogin()
|
||||
|
||||
console.log('App Show')
|
||||
})
|
||||
|
||||
@@ -13,6 +13,8 @@ interface ImportMetaEnv {
|
||||
readonly VITE_SERVER_PORT: string
|
||||
/** 是否清除console */
|
||||
readonly VITE_DELETE_CONSOLE: string
|
||||
|
||||
readonly VITE_ALIYUN_BUCKET: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const whiteList = [
|
||||
'/pages-sub/login/index',
|
||||
'/pages/account/index',
|
||||
'/pages-sub/login/index'
|
||||
]
|
||||
|
||||
export const navigateToInterceptor = {
|
||||
@@ -34,9 +33,9 @@ export const navigateToInterceptor = {
|
||||
|
||||
export const routeInterceptor = {
|
||||
install() {
|
||||
// uni.addInterceptor('navigateTo', navigateToInterceptor)
|
||||
// uni.addInterceptor('reLaunch', navigateToInterceptor)
|
||||
// uni.addInterceptor('redirectTo', navigateToInterceptor)
|
||||
// uni.addInterceptor('switchTab', navigateToInterceptor)
|
||||
uni.addInterceptor('navigateTo', navigateToInterceptor)
|
||||
uni.addInterceptor('reLaunch', navigateToInterceptor)
|
||||
uni.addInterceptor('redirectTo', navigateToInterceptor)
|
||||
uni.addInterceptor('switchTab', navigateToInterceptor)
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<script setup lang="ts">
|
||||
import type { UploadFile, UploadFileItem } from 'sard-uniapp'
|
||||
import { isImageUrl, isVideoUrl, toast } from 'sard-uniapp'
|
||||
import { aliyunpluploadApi, delSubRecordApi, searchdataApi } from '@/request/api'
|
||||
import { downloadFile, formatFileSize, imageCompress, isImage, uploadFileToAliyun } from '@/utils/file'
|
||||
import { isH5 } from '@/utils/platform'
|
||||
|
||||
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}'`
|
||||
}
|
||||
searchdataApi({
|
||||
viewname: 'bf_files',
|
||||
searchcondition,
|
||||
orderfield: '',
|
||||
}).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) {
|
||||
if (!isImageUrl(fileItem.mx_mapfilename) && !isVideoUrl(fileItem.mx_mapfilename)) {
|
||||
downloadFile(fileItem.mx_mapfilename)
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
catch (err: any) {
|
||||
console.error('上传失败:', err)
|
||||
fileItem.status = 'failed'
|
||||
fileItem.message = err.message || '上传失败'
|
||||
fileList.value = [...fileList.value]
|
||||
}
|
||||
}
|
||||
|
||||
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-upload v-model="fileList" :readonly="!isEdit" :after-read="afterRead" :before-read="beforeRead" multiple @item-click="onItemClick" @remove="onRemove" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file {
|
||||
padding: 36rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -34,47 +34,35 @@ function onSubmit() {
|
||||
formRef.value
|
||||
?.validate()
|
||||
.then(() => {
|
||||
userStore.userInfo.orgid = formModel.orgid
|
||||
userStore.userInfo.userid = formModel.userid
|
||||
userStore.userInfo.token = '123'
|
||||
_loading.value = true
|
||||
loginOrgApi({
|
||||
orgid: formModel.orgid,
|
||||
userid: formModel.userid,
|
||||
password: formModel.password,
|
||||
}).then((res) => {
|
||||
if (res.data) {
|
||||
userStore.userInfo.orgid = formModel.orgid
|
||||
userStore.userInfo.userid = formModel.userid
|
||||
userStore.userInfo.token = res.data
|
||||
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
})
|
||||
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index',
|
||||
})
|
||||
}
|
||||
else {
|
||||
uni.showToast({
|
||||
title: '登录失败,请稍后再试',
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
}).finally(() => {
|
||||
_loading.value = false
|
||||
})
|
||||
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index',
|
||||
})
|
||||
// _loading.value = true
|
||||
// loginOrgApi({
|
||||
// orgid: formModel.orgid,
|
||||
// userid: formModel.userid,
|
||||
// password: formModel.password,
|
||||
// }).then((res) => {
|
||||
// if (res.data) {
|
||||
// userStore.userInfo.orgid = formModel.orgid
|
||||
// userStore.userInfo.userid = formModel.userid
|
||||
// userStore.userInfo.token = res.data
|
||||
|
||||
// uni.showToast({
|
||||
// title: '登录成功',
|
||||
// icon: 'success',
|
||||
// })
|
||||
|
||||
// uni.switchTab({
|
||||
// url: '/pages/home/index',
|
||||
// })
|
||||
// }
|
||||
// else {
|
||||
// uni.showToast({
|
||||
// title: '登录失败,请稍后再试',
|
||||
// icon: 'error',
|
||||
// })
|
||||
// }
|
||||
// }).finally(() => {
|
||||
// _loading.value = false
|
||||
// })
|
||||
})
|
||||
.catch((error: FieldValidateError[]) => {
|
||||
toast.fail(error[0].message)
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
<script lang="ts" setup>
|
||||
import type { FieldValidateError, FormExpose, FormRules } from 'sard-uniapp'
|
||||
import { getWindowInfo, toast } from 'sard-uniapp'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { saveobjtApi, searchdataApi } 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 searchRes = await searchdataApi({
|
||||
viewname: 'b_user',
|
||||
searchcondition: `b_id = '${userStore.userInfo.userid}' and b_password = '${formModel.oldPassword}'`,
|
||||
orderfield: 'b_id',
|
||||
})
|
||||
|
||||
if (!searchRes.data || searchRes.data.length === 0) {
|
||||
toast.fail('旧密码错误,请重新输入')
|
||||
return
|
||||
}
|
||||
|
||||
const updateObj = {
|
||||
b_id: userStore.userInfo.userid,
|
||||
b_password: formModel.newPassword,
|
||||
}
|
||||
|
||||
const saveobjtRes = await saveobjtApi({
|
||||
tables: '[b_user]',
|
||||
insertValues: '[]',
|
||||
updateValues: `[${JSON.stringify(updateObj)}]`,
|
||||
delValues: '[]',
|
||||
keys: 'b_id',
|
||||
})
|
||||
|
||||
if (saveobjtRes.data === 'OK') {
|
||||
toast.success('密码修改成功,请重新登录')
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: '/pages-sub/login/index',
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
else {
|
||||
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 {
|
||||
// 7️⃣ 关闭 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">
|
||||
<template #custom="{ fieldId }">
|
||||
<view class="form-label" :class="fieldId">
|
||||
旧密码
|
||||
</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>
|
||||
</template>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="password">
|
||||
<template #custom="{ fieldId }">
|
||||
<view class="form-label" :class="fieldId">
|
||||
新密码
|
||||
</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>
|
||||
</template>
|
||||
</sar-form-item-plain>
|
||||
<sar-form-item-plain name="password">
|
||||
<template #custom="{ fieldId }">
|
||||
<view class="form-label" :class="fieldId">
|
||||
确认密码
|
||||
</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>
|
||||
</template>
|
||||
</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: 42rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
.form-subtitle {
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include flexGap(36rpx, column);
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.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>
|
||||
@@ -0,0 +1,310 @@
|
||||
<script setup lang="ts">
|
||||
import { toast } from 'sard-uniapp'
|
||||
import { ref } from 'vue'
|
||||
import { searchdatapageindexApi } from '@/request/api'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const pagingRef = ref<any>(null)
|
||||
const dataList = ref<any[]>([])
|
||||
|
||||
// 自定义 tabs
|
||||
const tabList = computed(() => [
|
||||
{ name: '未完成', count: 0 },
|
||||
{ name: '已完成', count: 0 },
|
||||
{ name: '全部', count: 0 },
|
||||
])
|
||||
const activeTab = ref(tabList.value[0])
|
||||
|
||||
// 搜索关键字
|
||||
const searchValue = ref('')
|
||||
|
||||
// 切换 tab
|
||||
function switchTab(tab: any) {
|
||||
activeTab.value = tab
|
||||
|
||||
pagingRef.value.reload()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch() {
|
||||
pagingRef.value.reload()
|
||||
}
|
||||
|
||||
// 模拟分页请求
|
||||
function queryList(pageNo: number, pageSize: number) {
|
||||
toast.loading('正在加载中')
|
||||
|
||||
const userid = userStore.userInfo.userid
|
||||
|
||||
let searchcondition = `2>1 AND b_kd_finish = '1' AND b_yx_finish = '1' `
|
||||
|
||||
if (activeTab.value.name === '未完成') {
|
||||
searchcondition += ` AND ISNULL(b_dc_finish,'') <> '1' AND ISNULL(b_dcman_id,'') IN ('', '${userid}')`
|
||||
}
|
||||
else if (activeTab.value.name === '已完成') {
|
||||
searchcondition += ` AND ISNULL(b_dc_finish,'') = '1' AND ISNULL(b_dcman_id,'') = '${userid}'`
|
||||
}
|
||||
else {
|
||||
searchcondition += ` AND (
|
||||
(ISNULL(b_dc_finish,'') <> '1' AND ISNULL(b_dcman_id,'') IN ('', '${userid}'))
|
||||
OR (ISNULL(b_dc_finish,'') = '1' AND ISNULL(b_dcman_id,'') = '${userid}')
|
||||
)`
|
||||
}
|
||||
|
||||
if (searchValue.value) {
|
||||
searchcondition += ` and (b_conno like '%${searchValue.value}%')`
|
||||
}
|
||||
|
||||
searchdatapageindexApi({
|
||||
viewname: 'v_xc_conyard_in',
|
||||
searchcondition,
|
||||
userid,
|
||||
page: pageNo,
|
||||
rows: pageSize,
|
||||
orderfield: 'b_jcdatetime desc',
|
||||
})
|
||||
.then((res) => {
|
||||
const rows = res.data.rows || []
|
||||
pagingRef.value.complete(rows)
|
||||
})
|
||||
.finally(() => {
|
||||
toast.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function handleToFile(itemData) {
|
||||
uni.navigateTo({
|
||||
url: `/pages-sub/file/index?moduleid=xc_conyard_in&father=${itemData.b_id}&cateid=014&edit=1`,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<z-paging ref="pagingRef" v-model="dataList" @query="queryList">
|
||||
<template #top>
|
||||
<sar-search
|
||||
v-model="searchValue"
|
||||
placeholder="请输入箱号搜索"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<view class="tabs">
|
||||
<view
|
||||
v-for="tab in tabList"
|
||||
:key="tab.name"
|
||||
class="tabs__item"
|
||||
:class="{ 'tabs__item--active': activeTab.name === tab.name }"
|
||||
@click="switchTab(tab)"
|
||||
>
|
||||
<sar-badge :value="tab.count">
|
||||
{{ tab.name }}
|
||||
</sar-badge>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 列表内容 -->
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="index"
|
||||
class="list-item"
|
||||
>
|
||||
<view class="list-item__header">
|
||||
<view class="list-item__main">
|
||||
箱号:{{ item.b_conno }}
|
||||
</view>
|
||||
<view class="list-item__extra">
|
||||
<sar-tag v-if="item.b_dc_finish === '1'" theme="success" size="small">
|
||||
已完成
|
||||
</sar-tag>
|
||||
<sar-tag v-else>
|
||||
未完成
|
||||
</sar-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list-item__body">
|
||||
<sar-row>
|
||||
<sar-col :span="12">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
进场单号:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_id }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="12">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
进场指令号:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_blno }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="6">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
箱型:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_contype }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="6">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
空重:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_conkz }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="6">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
箱态:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_constate }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="6">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
箱况:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_conxk }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
<sar-col :span="6">
|
||||
<view class="list-item__info">
|
||||
<view class="list-item__label">
|
||||
箱位:
|
||||
</view>
|
||||
<view class="list-item__value">
|
||||
{{ item.b_xwt }}
|
||||
</view>
|
||||
</view>
|
||||
</sar-col>
|
||||
</sar-row>
|
||||
</view>
|
||||
|
||||
<view class="list-item__footer">
|
||||
<sar-button inline size="mini" square @click="handleToFile(item)">
|
||||
拍照
|
||||
</sar-button>
|
||||
<sar-button
|
||||
v-if="item.b_dc_finish !== '1'"
|
||||
inline
|
||||
square
|
||||
type="default"
|
||||
theme="success"
|
||||
size="mini"
|
||||
>
|
||||
确认
|
||||
</sar-button>
|
||||
</view>
|
||||
<view class="list-item__line" />
|
||||
</view>
|
||||
</z-paging>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/style/mixins.scss';
|
||||
|
||||
/* tab 栏 */
|
||||
.tabs {
|
||||
display: flex;
|
||||
border-bottom: 2rpx solid #eee;
|
||||
background-color: #fff;
|
||||
|
||||
.tabs__item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
font-size: 30rpx;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.tabs__item--active {
|
||||
color: var(--sar-primary);
|
||||
font-weight: bold;
|
||||
border-bottom: 4rpx solid var(--sar-primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* 列表项 */
|
||||
.list-item {
|
||||
position: relative;
|
||||
padding: 16rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.list-item__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.list-item__main {
|
||||
font-weight: bold;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__body {
|
||||
.list-item__info {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
width: 100%;
|
||||
font-size: 26rpx;
|
||||
line-height: 1;
|
||||
margin-top: 16rpx;
|
||||
|
||||
.list-item__label {
|
||||
display: block;
|
||||
width: 5rem;
|
||||
color: #4b5563;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-item__value {
|
||||
flex: 1;
|
||||
color: #111827;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__footer {
|
||||
margin-top: 16rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@include flexGap(36rpx, '');
|
||||
|
||||
:deep(.sar-button) {
|
||||
padding: 0rpx 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item__line {
|
||||
position: absolute;
|
||||
bottom: 0rpx;
|
||||
left: 0rpx;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: #dcdcdc;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -52,7 +52,7 @@
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom"
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -66,6 +66,27 @@
|
||||
"navigationBarTitleText": "登录",
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "file/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "附件管理",
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "update-password/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改密码",
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "xcjin/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "进场堆高机",
|
||||
"navigationStyle": "default"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ function handleLoginOut() {
|
||||
title: '提示',
|
||||
message: '确定退出登录?',
|
||||
onConfirm() {
|
||||
toast.success('退出成功')
|
||||
userStore.reset()
|
||||
|
||||
uni.navigateTo({
|
||||
@@ -18,27 +17,75 @@ function handleLoginOut() {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handleToLogin() {
|
||||
if (userStore.isLogined) {
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages-sub/login/index',
|
||||
})
|
||||
}
|
||||
|
||||
function handleToUpdatePassword() {
|
||||
handleToLogin()
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages-sub/update-password/index',
|
||||
})
|
||||
}
|
||||
|
||||
const avatarText = computed(() => {
|
||||
if (!userStore.isLogined) {
|
||||
return '登'
|
||||
}
|
||||
|
||||
const id = userStore.userInfo?.userid
|
||||
if (!id || id.length === 0)
|
||||
return 'A'
|
||||
|
||||
return id.charAt(0).toUpperCase()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="account-container">
|
||||
<view class="account-header">
|
||||
<sar-avatar background="#7f8c8d" color="#fff">
|
||||
A
|
||||
<view>
|
||||
<view class="account-header" @click="handleToLogin">
|
||||
<sar-avatar size="96rpx" icon-size="48rpx" background="var(--sar-primary)" color="#fff">
|
||||
{{ avatarText }}
|
||||
</sar-avatar>
|
||||
<view class="user-info">
|
||||
<text class="user-account">
|
||||
123
|
||||
<text class="user-userid">
|
||||
{{ userStore.isLogined ? userStore.userInfo.userid : "尚未登录!" }}
|
||||
</text>
|
||||
<text class="user-orgid">
|
||||
123
|
||||
{{ userStore.isLogined ? userStore.userInfo.orgid : "点击前去登录。" }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="actions">
|
||||
<sar-list-item title="修改资料" />
|
||||
<sar-list-item title="退出登录" value="值" />
|
||||
<sar-list-item title="修改密码" hover arrow @click="handleToUpdatePassword">
|
||||
<template #icon>
|
||||
<sar-icon
|
||||
family="iconfont"
|
||||
name="updatePassword"
|
||||
color="var(--sar-primary)"
|
||||
size="36rpx"
|
||||
/>
|
||||
</template>
|
||||
</sar-list-item>
|
||||
|
||||
<sar-list-item title="退出登录" hover arrow @click="handleLoginOut">
|
||||
<template #icon>
|
||||
<sar-icon
|
||||
family="iconfont"
|
||||
name="exitLogin"
|
||||
color="var(--sar-primary)"
|
||||
size="36rpx"
|
||||
/>
|
||||
</template>
|
||||
</sar-list-item>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -47,34 +94,30 @@ function handleLoginOut() {
|
||||
.account-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 40rpx 32rpx;
|
||||
background-color: #2c3e50; /* 工业风深色 */
|
||||
border-radius: 2rpx; /* 轻微卡片感 */
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
|
||||
padding: 36rpx 28rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-left: 32rpx;
|
||||
color: #fff;
|
||||
|
||||
.user-account {
|
||||
font-size: 34rpx;
|
||||
justify-content: space-between;
|
||||
.user-userid {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
line-height: 42rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.user-orgid {
|
||||
font-size: 28rpx;
|
||||
margin-top: 6rpx;
|
||||
margin-top: 12rpx;
|
||||
color: #6b788e;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions{
|
||||
.actions {
|
||||
margin-top: 32rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -7,6 +7,15 @@ const swiperList = [
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
function toLinkUrl(url) {
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -70,6 +79,12 @@ const swiperList = [
|
||||
<text>内容</text>
|
||||
</view>
|
||||
</sar-grid-item>
|
||||
<sar-grid-item @click="toLinkUrl('/pages-sub/xcjin/index')">
|
||||
<view class="grid-item">
|
||||
<image src="@/static/images/柴犬.png" />
|
||||
<text>进场堆高机</text>
|
||||
</view>
|
||||
</sar-grid-item>
|
||||
</sar-grid>
|
||||
</view>
|
||||
</view>
|
||||
@@ -85,6 +100,9 @@ const swiperList = [
|
||||
}
|
||||
.grid-container {
|
||||
margin-top: 32rpx;
|
||||
:deep(.sar-grid__content) {
|
||||
background-color: var(--sar-primary);
|
||||
}
|
||||
.grid-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -98,6 +116,7 @@ const swiperList = [
|
||||
text {
|
||||
margin-top: 16rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,3 +38,67 @@ interface GetAutocompleteDataExParams {
|
||||
export function getAutocompleteDataExApi(params: GetAutocompleteDataExParams) {
|
||||
return request.postForm('/getAutocompleteDataEx.jsp', params)
|
||||
}
|
||||
|
||||
interface SaveobjtParams {
|
||||
tables: string
|
||||
insertValues: string
|
||||
delValues: string
|
||||
updateValues: string
|
||||
keys: string
|
||||
}
|
||||
|
||||
export function saveobjtApi(params: SaveobjtParams) {
|
||||
return request.postForm('/saveobjt.jsp', params)
|
||||
}
|
||||
|
||||
interface SearchdataParams {
|
||||
viewname: string
|
||||
searchcondition: string
|
||||
orderfield: string
|
||||
}
|
||||
export function searchdataApi(params: SearchdataParams) {
|
||||
return request.postForm('/searchdata.jsp', params)
|
||||
}
|
||||
|
||||
interface SearchdatapageindexParams {
|
||||
viewname: string
|
||||
searchcondition: string
|
||||
userid: string
|
||||
orderfield: string
|
||||
page: number
|
||||
rows: number
|
||||
}
|
||||
|
||||
export function searchdatapageindexApi(params: SearchdatapageindexParams) {
|
||||
return request.postForm(`/searchdatapageindex.jsp`, params)
|
||||
}
|
||||
interface DelSubRecordParams {
|
||||
id: string
|
||||
module: string
|
||||
bucketName: string
|
||||
}
|
||||
export function delSubRecordApi(params: DelSubRecordParams) {
|
||||
return request.postForm('/DelSubRecord.jsp', params)
|
||||
}
|
||||
|
||||
interface getaliyunkeyParams {
|
||||
orgid: string
|
||||
bucket: string
|
||||
}
|
||||
|
||||
export function getaliyunkeyApi(params: getaliyunkeyParams) {
|
||||
return request.postForm(`/getaliyunkey.jsp`, params)
|
||||
}
|
||||
|
||||
interface aliyunpluploadParams {
|
||||
despathfile: string
|
||||
myfilename: string
|
||||
size: string
|
||||
tablename: string
|
||||
sid: string
|
||||
mx_moduleid: string
|
||||
mx_cate_id: string
|
||||
}
|
||||
export function aliyunpluploadApi(params: aliyunpluploadParams) {
|
||||
return request.postForm(`/aliyunplupload.jsp`, params)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ function request<T = any>(option: UniApp.RequestOptions): Promise<IResData<T>> &
|
||||
}
|
||||
catch {
|
||||
// 如果解析失败,保持原始字符串即可
|
||||
console.warn('data.data 不是合法 JSON 字符串', data.data)
|
||||
// console.warn('data.data 不是合法 JSON 字符串', data.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
@font-face {
|
||||
font-family: 'iconfont'; /* Project id 5031675 */
|
||||
src: url('data:font/ttf;charset=utf-8;base64,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 truncated
|
||||
src: url('data:font/ttf;charset=utf-8;base64,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 truncated
|
||||
format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: 'iconfont' !important;
|
||||
font-size: 32rpx;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconfont-updatePassword:before {
|
||||
content: '\e628';
|
||||
}
|
||||
|
||||
.iconfont-exitLogin:before {
|
||||
content: '\e600';
|
||||
}
|
||||
|
||||
.iconfont-chaiquan:before {
|
||||
content: '\e647';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
import { getaliyunkeyApi } from '@/request/api'
|
||||
import { useUserStore } from '@/store'
|
||||
import { isH5 } from './platform'
|
||||
|
||||
const aliyunBucket = import.meta.env.VITE_ALIYUN_BUCKET
|
||||
|
||||
/**
|
||||
* 压缩图片(多端通用)
|
||||
* @param url 图片路径
|
||||
* @param name 图片名称
|
||||
* @returns Promise<{ path: string, size: number }>
|
||||
*/
|
||||
export async function imageCompress(url: string): Promise<{ path: string, size: number }> {
|
||||
// #ifndef H5
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.compressImage({
|
||||
src: url,
|
||||
quality: 80,
|
||||
success: async (res) => {
|
||||
try {
|
||||
// 获取文件信息
|
||||
const fileInfo = await uni.getFileInfo({ filePath: res.tempFilePath })
|
||||
resolve({
|
||||
path: res.tempFilePath,
|
||||
size: fileInfo.size,
|
||||
})
|
||||
}
|
||||
catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
},
|
||||
fail: reject,
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.crossOrigin = 'Anonymous'
|
||||
img.src = url
|
||||
|
||||
img.onload = () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')!
|
||||
const maxSize = 600
|
||||
let { width, height } = img
|
||||
|
||||
// 按比例压缩
|
||||
if (width > height && width > maxSize) {
|
||||
height = (maxSize * height) / width
|
||||
width = maxSize
|
||||
}
|
||||
else if (height > width && height > maxSize) {
|
||||
width = (maxSize * width) / height
|
||||
height = maxSize
|
||||
}
|
||||
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
ctx.drawImage(img, 0, 0, width, height)
|
||||
|
||||
const base64 = canvas.toDataURL('image/jpeg', 0.8)
|
||||
|
||||
// 计算 Base64 大小
|
||||
const sizeInBytes = Math.round((base64.length - (base64.indexOf(',') + 1)) * 0.75)
|
||||
|
||||
resolve({
|
||||
path: base64,
|
||||
size: sizeInBytes,
|
||||
})
|
||||
}
|
||||
catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
|
||||
img.onerror = reject
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件名是否为图片类型
|
||||
* @param fileName 文件名(如 "photo.png"、"avatar.JPG")
|
||||
*/
|
||||
export function isImage(fileName: string): boolean {
|
||||
if (!fileName || typeof fileName !== 'string')
|
||||
return false
|
||||
|
||||
// 常见图片扩展名(全小写)
|
||||
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'heic']
|
||||
|
||||
// 取文件名的后缀
|
||||
const ext = fileName.split('.').pop()?.toLowerCase()
|
||||
|
||||
// 检查是否在图片后缀列表中
|
||||
return !!ext && imageExtensions.includes(ext)
|
||||
}
|
||||
|
||||
// 文件大小格式化
|
||||
export function formatFileSize(size: number): string {
|
||||
if (size < 1024)
|
||||
return `${size} B`
|
||||
else if (size < 1024 * 1024)
|
||||
return `${(size / 1024).toFixed(2)} KB`
|
||||
else if (size < 1024 * 1024 * 1024)
|
||||
return `${(size / (1024 * 1024)).toFixed(2)} MB`
|
||||
else return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`
|
||||
}
|
||||
|
||||
export interface AliyunUploadResult {
|
||||
url: string // 上传后的完整 URL
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到阿里云 OSS
|
||||
* @param filePath 本地文件路径
|
||||
* @param fileName 文件名
|
||||
* @param fileType 文件类型,可选:image/video/file
|
||||
* @returns Promise<AliyunUploadResult>
|
||||
*/
|
||||
export async function uploadFileToAliyun(
|
||||
filePath: string,
|
||||
fileName: string,
|
||||
fileType: any,
|
||||
): Promise<AliyunUploadResult> {
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 获取 OSS 临时上传凭证
|
||||
const keyRes = await getaliyunkeyApi({
|
||||
orgid: userStore.userInfo.orgid,
|
||||
bucket: aliyunBucket,
|
||||
})
|
||||
const { accessid, callback, dir, host, policy, signature } = keyRes.data
|
||||
|
||||
// 构建文件在 OSS 的存储路径
|
||||
const fileExtension = fileName.split('.').pop()?.toLowerCase() || 'tmp'
|
||||
const timestamp = Date.now()
|
||||
const random = Math.floor(Math.random() * 1000)
|
||||
const key = `${dir}/${timestamp + random}.${fileExtension}`
|
||||
|
||||
const formData: Record<string, any> = {
|
||||
key,
|
||||
OSSAccessKeyId: accessid,
|
||||
policy,
|
||||
signature,
|
||||
success_action_status: '200',
|
||||
name: fileName,
|
||||
}
|
||||
if (callback)
|
||||
formData.callback = callback
|
||||
|
||||
// 使用 Promise 包裹 uni.uploadFile
|
||||
return new Promise<AliyunUploadResult>((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: host,
|
||||
filePath,
|
||||
name: 'file',
|
||||
fileName,
|
||||
fileType,
|
||||
formData,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
resolve({
|
||||
url: `${host}/${key}`,
|
||||
})
|
||||
}
|
||||
else {
|
||||
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function downloadFile(fileUrl: string, fileName?: string) {
|
||||
if (isH5) {
|
||||
// H5 平台下载逻辑
|
||||
const name = fileName || fileUrl.split('/').pop() || 'file'
|
||||
const a = document.createElement('a')
|
||||
a.href = fileUrl
|
||||
a.download = name
|
||||
a.target = '_blank'
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
console.log('H5 文件下载已触发:', name)
|
||||
}
|
||||
else {
|
||||
// APP / 小程序下载逻辑
|
||||
uni.downloadFile({
|
||||
url: fileUrl,
|
||||
success: (response) => {
|
||||
if (response.statusCode === 200 && response.tempFilePath) {
|
||||
uni.saveFile({
|
||||
tempFilePath: response.tempFilePath,
|
||||
success: (resData) => {
|
||||
console.log('保存路径', resData.savedFilePath)
|
||||
uni.showToast({ title: '下载成功' })
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('保存失败', error)
|
||||
},
|
||||
})
|
||||
}
|
||||
else {
|
||||
console.error('下载失败或 tempFilePath 不存在', response)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('downloadFile 失败', err)
|
||||
},
|
||||
progress: (res) => {
|
||||
console.log(`下载进度: ${res.progress}%`)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
// 定义单位的类型
|
||||
type Unit = 'day' | 'week' | 'month' | 'year'
|
||||
|
||||
/**
|
||||
* 获取指定日期之前的日期
|
||||
* @param value 数字,表示要减去的时间量
|
||||
* @param unit 时间单位,可以是 'day'、'week'、'month' 或 'year'
|
||||
* @returns 返回计算后的日期
|
||||
*/
|
||||
export function getDateBefore(value: number, unit: Unit): string {
|
||||
return dayjs().subtract(value, unit).format('YYYY-MM-DD')
|
||||
}
|
||||
export function getTimeDifference(dateStr1: string, dateStr2: string) {
|
||||
const date1 = new Date(dateStr1)
|
||||
|
||||
if (!dateStr2) {
|
||||
return Number.NaN
|
||||
}
|
||||
|
||||
const date2 = new Date(dateStr2)
|
||||
const differenceInMilliseconds = date2.getTime() - date1.getTime()
|
||||
|
||||
return differenceInMilliseconds
|
||||
}
|
||||
// 获取当前年份
|
||||
|
||||
export function getYear(): string {
|
||||
return dayjs().year().toString()
|
||||
}
|
||||
export function getMonth(): string {
|
||||
// 获取当前月份并加1,确保是1-12范围
|
||||
const month = (dayjs().month() + 1).toString()
|
||||
return month.padStart(2, '0') // 如果是单数月,前面加0
|
||||
}
|
||||
|
||||
export function getDay(): string {
|
||||
// 获取当前日期并转换为字符串
|
||||
const day = dayjs().date().toString()
|
||||
return day.padStart(2, '0') // 如果是单数天,前面加0
|
||||
}
|
||||
|
||||
export function getCurrentDate() {
|
||||
return dayjs().format('YYYY-MM-DD')
|
||||
}
|
||||
export function getCurrentDateTimeWithSeconds() {
|
||||
return dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
export function stringToTimestamp(timeString: string, format: string): number {
|
||||
const parsedDate = dayjs(timeString, format)
|
||||
if (!parsedDate.isValid()) {
|
||||
throw new Error('Invalid date string or format')
|
||||
}
|
||||
return parsedDate.valueOf() // 返回时间戳(以毫秒为单位)
|
||||
}
|
||||
export function timestampToString(timestamp: number, format: string): string {
|
||||
const parsedDate = dayjs(timestamp)
|
||||
return parsedDate.format(format)
|
||||
}
|
||||
/**
|
||||
* 判断传入日期是否在今天的60天以内(含60天)
|
||||
* @param dateStr - 日期字符串(如 '2025-02-01')
|
||||
* @returns boolean - true 表示在60天内(包括第60天),false 表示超过60天
|
||||
*/
|
||||
export function isWithin60Days(dateStr: string): boolean {
|
||||
if (!dateStr.trim()) {
|
||||
return true
|
||||
}
|
||||
const inputDate = dayjs(dateStr)
|
||||
const today = dayjs()
|
||||
const diffDays = today.diff(inputDate, 'day')
|
||||
return diffDays >= 0 && diffDays <= 60
|
||||
}
|
||||
@@ -1,138 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>个人中心</title>
|
||||
<style>
|
||||
:root {
|
||||
--theme-color: #2c3e50;
|
||||
--text-main: #2c3e50;
|
||||
--text-sub: #7f8c8d;
|
||||
--bg-light: #f4f5f7;
|
||||
--card-bg: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "SF Pro Text", "Roboto", "Segoe UI", Arial, sans-serif;
|
||||
background: var(--bg-light);
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
/* 卡片式 Header */
|
||||
.header-card {
|
||||
background: var(--theme-color);
|
||||
color: #fff;
|
||||
margin: 20px 16px 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
background: #7f8c8d;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
font-size: 14px;
|
||||
color: #c0cfd8;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.user-details span {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #d0d6db;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 操作按钮区 */
|
||||
.actions {
|
||||
margin: 28px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: var(--theme-color);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 14px 0;
|
||||
font-size: 15px;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: #1e2d3a;
|
||||
}
|
||||
|
||||
.btn.secondary {
|
||||
background: transparent;
|
||||
color: var(--theme-color);
|
||||
border: 1px solid var(--theme-color);
|
||||
}
|
||||
|
||||
.btn.secondary:hover {
|
||||
background: rgba(44,62,80,0.05);
|
||||
}
|
||||
|
||||
/* 底部 */
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>附件管理</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.header {
|
||||
background-color: #2c3e50;
|
||||
color: #fff;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
.upload-area {
|
||||
background: #fff;
|
||||
margin: 15px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
||||
}
|
||||
.upload-area input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
.upload-label {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
border: 2px dashed #ccc;
|
||||
border-radius: 8px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
.attachment-list {
|
||||
margin: 15px;
|
||||
}
|
||||
.attachment-item {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
||||
}
|
||||
.attachment-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.attachment-thumb {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
.attachment-name {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
.attachment-actions button {
|
||||
margin-left: 5px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: #2c3e50;
|
||||
color: white;
|
||||
}
|
||||
.btn-danger {
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 卡片式 Header -->
|
||||
<div class="header-card">
|
||||
<div class="avatar">U</div>
|
||||
<div class="user-info">
|
||||
<div class="welcome">欢迎登录!</div>
|
||||
<div class="user-name">张三</div>
|
||||
<div class="user-details">
|
||||
<span>账号:zhangsan</span>
|
||||
<span>机构码:A-102938</span>
|
||||
<div class="header">附件管理</div>
|
||||
|
||||
<div class="upload-area">
|
||||
<label for="file-upload" class="upload-label">点击上传附件</label>
|
||||
<input type="file" id="file-upload" multiple />
|
||||
</div>
|
||||
|
||||
<div class="attachment-list">
|
||||
<div class="attachment-item">
|
||||
<div class="attachment-info">
|
||||
<img src="https://via.placeholder.com/50" class="attachment-thumb" />
|
||||
<div class="attachment-name">工单图片1.jpg</div>
|
||||
</div>
|
||||
<div class="attachment-actions">
|
||||
<button class="btn-primary">预览</button>
|
||||
<button class="btn-danger">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="attachment-item">
|
||||
<div class="attachment-info">
|
||||
<div class="attachment-thumb"></div>
|
||||
<div class="attachment-name">报告文档.pdf</div>
|
||||
</div>
|
||||
<div class="attachment-actions">
|
||||
<button class="btn-primary">预览</button>
|
||||
<button class="btn-danger">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮区 -->
|
||||
<div class="actions">
|
||||
<button class="btn">修改资料</button>
|
||||
<button class="btn secondary">退出登录</button>
|
||||
</div>
|
||||
|
||||
<!-- 底部 -->
|
||||
<div class="footer">© 2025 工业控制系统中心</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user