提交 188f2da5 authored 作者: lidongxu's avatar lidongxu

Merge branch 'release' into dev

...@@ -16,11 +16,11 @@ VITE_APP_REDIRECT_URL = 'http://localhost:8085' ...@@ -16,11 +16,11 @@ VITE_APP_REDIRECT_URL = 'http://localhost:8085'
# 积木报表服务地址 # 积木报表服务地址
VITE_APP_REPORT_URL = 'https://sfa-qa.wxl66.cn' VITE_APP_REPORT_URL = 'https://sfa-qa.wxl66.cn'
# 积木报表预览地址 # 积木报表预览地址
VITE_APP_REPORT_PREVIEW_URL = '/report/jmreport/view' VITE_APP_REPORT_PREVIEW_URL = '#/report/jmreport/view'
# 积木报表分享预览地址 # 积木报表分享预览地址
VITE_APP_REPORT_SHARE_PREVIEW_URL = '/report' VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
# 积木报表编辑地址 # 积木报表编辑地址
VITE_APP_REPORT_EDIT_URL = '/report/jmreport/index' VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 模板表格 # 模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx' VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
...@@ -15,11 +15,11 @@ VITE_APP_REDIRECT_URL = 'https://sfa.wxl66.cn/link/' ...@@ -15,11 +15,11 @@ VITE_APP_REDIRECT_URL = 'https://sfa.wxl66.cn/link/'
# 积木报表服务地址 # 积木报表服务地址
VITE_APP_REPORT_URL = 'https://sfa.wxl66.cn' VITE_APP_REPORT_URL = 'https://sfa.wxl66.cn'
# 积木报表预览地址 # 积木报表预览地址
VITE_APP_REPORT_PREVIEW_URL = '/report/jmreport/view' VITE_APP_REPORT_PREVIEW_URL = '#/report/jmreport/view'
# 积木报表分享预览地址 # 积木报表分享预览地址
VITE_APP_REPORT_SHARE_PREVIEW_URL = '/report' VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
# 积木报表编辑地址 # 积木报表编辑地址
VITE_APP_REPORT_EDIT_URL = '/report/jmreport/index' VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 模板表格 # 模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx' VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
...@@ -14,11 +14,11 @@ VITE_APP_REDIRECT_URL = 'https://sfa-qa.wxl66.cn/' ...@@ -14,11 +14,11 @@ VITE_APP_REDIRECT_URL = 'https://sfa-qa.wxl66.cn/'
# 积木报表服务地址 # 积木报表服务地址
VITE_APP_REPORT_URL = 'https://sfa-qa.wxl66.cn' VITE_APP_REPORT_URL = 'https://sfa-qa.wxl66.cn'
# 积木报表预览地址 # 积木报表预览地址
VITE_APP_REPORT_PREVIEW_URL = '/report/jmreport/view' VITE_APP_REPORT_PREVIEW_URL = '#/report/jmreport/view'
# 积木报表分享预览地址 # 积木报表分享预览地址
VITE_APP_REPORT_SHARE_PREVIEW_URL = '/report' VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
# 积木报表编辑地址 # 积木报表编辑地址
VITE_APP_REPORT_EDIT_URL = '/report/jmreport/index' VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 模板表格 # 模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx' VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
<template> <template>
<el-watermark :font="font" <template v-if="!isInWhiteList">
:content="content" <el-watermark :font="font"
class="wm-class"> :content="content"
class="wm-class">
<router-view />
</el-watermark>
</template>
<template v-else>
<router-view /> <router-view />
</el-watermark> </template>
<back-to-up /> <back-to-up />
</template> </template>
...@@ -11,6 +16,10 @@ ...@@ -11,6 +16,10 @@
import useSettingsStore from '@/store/modules/settings' import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme' import { handleThemeStyle } from '@/utils/theme'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { isWhiteList } from '@/permission'
const route = useRoute()
const isInWhiteList = computed(() => isWhiteList(route.path))
const content = computed(() => { const content = computed(() => {
return useUserStore().userInfo.nickName + ' ' + useUserStore().userInfo.phone return useUserStore().userInfo.nickName + ' ' + useUserStore().userInfo.phone
...@@ -19,14 +28,14 @@ const isDark = computed(() => { ...@@ -19,14 +28,14 @@ const isDark = computed(() => {
return useSettingsStore().isDark return useSettingsStore().isDark
}) })
const font = reactive({ const font = reactive({
color: 'rgba(0, 0, 0, .15)', color: 'rgba(0, 0, 0, .05)',
}) })
watch( watch(
isDark, isDark,
() => { () => {
font.color = isDark.value font.color = isDark.value
? 'rgba(255, 255, 255, 0.15)' ? 'rgba(255, 255, 255, 0.05)'
: 'rgba(0, 0, 0, .15)' : 'rgba(0, 0, 0, .05)'
}, },
{ {
immediate: true, immediate: true,
......
...@@ -73,9 +73,14 @@ export function logout() { ...@@ -73,9 +73,14 @@ export function logout() {
// 刷新 token 有效期 // 刷新 token 有效期
export function refreshToken() { export function refreshTokenAPI(refreshToken) {
return request({ return request({
url: '/auth/refresh', url: '/auth/refreshToken',
method: 'post' method: 'post',
headers: {
isToken: false, // 本次请求无需设置在请求拦截器设置请求头上的 token(容易把过期的 token 覆盖到 Authorization 了,而这次 Authorization 我带的是刷新的 refreshToken 给后端)
'Authorization': `Bearer ` + refreshToken
},
}) })
} }
...@@ -14,9 +14,9 @@ import useVersionStore from '@/store/modules/version' ...@@ -14,9 +14,9 @@ import useVersionStore from '@/store/modules/version'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
// 登录页,物流查询页 // 登录页,物流查询页
export const whiteList = ['/login', '/logistics'] const whiteList = ['/login', '/logistics']
const isWhiteList = (path) => { export const isWhiteList = (path) => {
return whiteList.some(pattern => isPathMatch(pattern, path)) return whiteList.some(pattern => isPathMatch(pattern, path))
} }
......
import { login, fsLogin, getInfo, qcLogin } from '@/api' import { login, fsLogin, getInfo, qcLogin, refreshTokenAPI } from '@/api'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken, getRefreshToken, setRefreshToken, removeRefreshToken } from '@/utils/auth'
import { isHttp, isEmpty } from "@/utils/validate" import { isHttp, isEmpty } from "@/utils/validate"
import defAva from '@/assets/images/profile.jpg' import defAva from '@/assets/images/profile.jpg'
...@@ -8,6 +9,7 @@ export default defineStore( ...@@ -8,6 +9,7 @@ export default defineStore(
{ {
state: () => ({ state: () => ({
token: getToken(), token: getToken(),
refreshToken: getRefreshToken(),
id: '', id: '',
name: '', name: '',
avatar: '', avatar: '',
...@@ -27,7 +29,9 @@ export default defineStore( ...@@ -27,7 +29,9 @@ export default defineStore(
const { username, password } = data const { username, password } = data
login({ username, password }).then(res => { login({ username, password }).then(res => {
this.token = res.data.access_token this.token = res.data.access_token
this.refreshToken = res.data.refresh_token
setToken(res.data.access_token) setToken(res.data.access_token)
setRefreshToken(res.data.refresh_token)
resolve() resolve()
}).catch(error => { }).catch(error => {
reject(error) reject(error)
...@@ -92,7 +96,13 @@ export default defineStore( ...@@ -92,7 +96,13 @@ export default defineStore(
// reject(error) // reject(error)
// }) // })
}) })
} },
// 刷新token
async refreshTokenFn() {
const res = await refreshTokenAPI(this.refreshToken)
this.token = res.data.access_token
setToken(res.data.access_token)
},
}, },
getters: { getters: {
/** /**
...@@ -109,7 +119,7 @@ export default defineStore( ...@@ -109,7 +119,7 @@ export default defineStore(
empId: state.userInfo.userId, // 员工 id empId: state.userInfo.userId, // 员工 id
empNo: state.userInfo.userName, // 员工工号 empNo: state.userInfo.userName, // 员工工号
empName: state.userInfo.nickName, // 员工昵称名字 empName: state.userInfo.nickName, // 员工昵称名字
} }
} }
} }
}) })
......
...@@ -14,8 +14,8 @@ export default defineStore( ...@@ -14,8 +14,8 @@ export default defineStore(
getVersion() { getVersion() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getVersionAPI().then(res => { getVersionAPI().then(res => {
this.versionChange = !(this.version === res.data[0].version) this.versionChange = !(this.version === res.data[0]?.version)
this.version = res.data[0].version this.version = res.data[0]?.version
// 组织版本内容数据 // 组织版本内容数据
this.versionList = res.data[0]?.changes.map(o => { this.versionList = res.data[0]?.changes.map(o => {
return { return {
......
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token' const TokenKey = 'Admin-Token'
const refreshToken = 'admin-t'
export function getToken() { export function getToken() {
return Cookies.get(TokenKey) return Cookies.get(TokenKey)
...@@ -13,3 +14,17 @@ export function setToken(token) { ...@@ -13,3 +14,17 @@ export function setToken(token) {
export function removeToken() { export function removeToken() {
return Cookies.remove(TokenKey) return Cookies.remove(TokenKey)
} }
export function getRefreshToken() {
return Cookies.get(refreshToken)
}
export function setRefreshToken(token) {
return Cookies.set(refreshToken, token)
}
export function removeRefreshToken() {
return Cookies.remove(refreshToken)
}
...@@ -6,7 +6,7 @@ import { tansParams, blobValidate } from '@/utils/ruoyi' ...@@ -6,7 +6,7 @@ import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache' import cache from '@/plugins/cache'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { fsClientAuth, refreshToken } from '@/api' import { fsClientAuth } from '@/api'
let downloadLoadingInstance; let downloadLoadingInstance;
// 是否显示重新登录 // 是否显示重新登录
...@@ -81,7 +81,6 @@ service.interceptors.request.use(config => { ...@@ -81,7 +81,6 @@ service.interceptors.request.use(config => {
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(async res => { service.interceptors.response.use(async res => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200; const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
...@@ -102,21 +101,29 @@ service.interceptors.response.use(async res => { ...@@ -102,21 +101,29 @@ service.interceptors.response.use(async res => {
return service(res.config) return service(res.config)
} }
// PC/移动端刷新 token 有效期 // PC/移动端刷新 token 有效期
// await refreshToken() // await useUserStore().refreshTokenFn()
// return service(res.config) // return service(res.config)
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
if (!isRelogin.show) { isRelogin.show = false;
isRelogin.show = true; useUserStore().logOut().then(() => {
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { location.href = '#/login';
isRelogin.show = false; })
useUserStore().logOut().then(() => { }).catch(() => {
location.href = '#/login'; isRelogin.show = false;
}) });
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 403) {
// 如果刷新 refreshToken 接口也报错了,证明需要重新登录
// ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
// isRelogin.show = false;
// useUserStore().logOut().then(() => {
// location.href = '#/login';
// })
// }).catch(() => {
// isRelogin.show = false;
// });
// return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) { } else if (code === 500) {
ElMessage({ message: msg, type: 'error' }) ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))
......
<template> <template>
<div class="app-container"> <div class="app-container">
<div class="container"> <el-row class="client-fix-height container">
<!-- 查询表单 --> <el-col>
<el-form :model="queryParams" <!-- 查询表单 -->
inline <el-form :model="queryParams"
label-position="left"> inline
<el-row> label-position="left">
<el-form-item label="安徽/北京单据编号" <el-row>
prop="sentNo"> <el-form-item label="安徽/北京单据编号"
<el-input v-model="queryParams.sentNo" prop="sentNo">
clearable <el-input v-model="queryParams.sentNo"
placeholder="输入要查询的安徽/北京单独单号" clearable
@input="getLogisticsReceiptList" placeholder="输入要查询的安徽/北京单独单号"
style="width: 250px;" /> @input="getLogisticsReceiptList"
</el-form-item> style="width: 250px;" />
<el-form-item label="快递单号" </el-form-item>
prop="expressNo"> <el-form-item label="快递单号"
<el-input v-model="queryParams.expressNo" prop="expressNo">
clearable <el-input v-model="queryParams.expressNo"
placeholder="输入要查询的快递单号" clearable
@input="getLogisticsReceiptList" /> placeholder="输入要查询的快递单号"
</el-form-item> @input="getLogisticsReceiptList" />
<el-form-item label="DD 单号查询" </el-form-item>
prop="ddNo"> <el-form-item label="DD 单号查询"
<el-input v-model="queryParams.ddNo" prop="ddNo">
clearable <el-input v-model="queryParams.ddNo"
placeholder="输入要查询的 DD 单号" clearable
@input="getLogisticsReceiptList" /> placeholder="输入要查询的 DD 单号"
</el-form-item> @input="getLogisticsReceiptList" />
<el-form-item label="物流公司编码" </el-form-item>
prop="transport"> <el-form-item label="物流公司编码"
<el-input v-model="queryParams.transport" prop="transport">
clearable <el-input v-model="queryParams.transport"
placeholder="输入要查询的物流公司编码" clearable
@input="getLogisticsReceiptList" placeholder="输入要查询的物流公司编码"
style="width: 220px;" /> @input="getLogisticsReceiptList"
</el-form-item> style="width: 220px;" />
<el-form-item label="订单状态" </el-form-item>
prop="isOperateEnd"> <el-form-item label="订单状态"
<el-select v-model="queryParams.isOperateEnd" prop="isOperateEnd">
placeholder="查询订单状态" <el-select v-model="queryParams.isOperateEnd"
clearable placeholder="查询订单状态"
@change="getLogisticsReceiptList"> clearable
<el-option label="已完成" @change="getLogisticsReceiptList">
value="true" /> <el-option label="已完成"
<el-option label="未完成" value="true" />
value="false" /> <el-option label="未完成"
</el-select> value="false" />
</el-form-item>
</el-row>
</el-form>
<!-- 数据表格 -->
<el-table :data="tableList"
border
style="width: 100%"
class="table-container">
<el-table-column v-for="item in columns"
:key="item.label"
:prop="item.prop"
:label="item.label"
:width="item.width"
:fixed="item.fixed"
:class-name="item.className">
<template #header="{ column }"
v-if="item.prop === 'receiptPhoto'">
<div class="header-container">
<span>{{ column.label }}</span>
<el-button @click="showPhoto = !showPhoto"
style="margin-left: 10px;">{{ showPhoto ? '隐藏' : '显示' }}图片</el-button>
</div>
</template>
<template #default="scope">
<template v-if="item.prop === 'receiptPhoto'">
<div class="receipt-photo-container"
v-if="showPhoto">
<span v-if="JSON.parse(scope.row[item.prop] || '[]').length === 0">暂无图片</span>
<el-image v-else
v-for="(urlStr, index) in JSON.parse(scope.row[item.prop] || '[]')"
:key="index"
:initial-index="index"
:preview-src-list="JSON.parse(scope.row[item.prop] || '[]')"
preview-teleported
:src="urlStr"
alt="图片"
class="receipt-photo-item"
fit="cover"
style="width: 80px; height: 50px; " />
</div>
</template>
<template v-else-if="item.prop === 'logisticsTrack'">
<el-button type="primary"
@click="handleLogisticsTrack(scope.row)"
text>
查看物流轨迹
</el-button>
</template>
<template v-else-if="item.prop === 'receiptPhotoCompleteFlag'">
<el-select v-model="scope.row[item.prop]"
placeholder="请选择"
style="width: 100%"
@change="handleReceiptPhotoChangeStatus(scope.row)">
<el-option v-for="item in receiptPhotoCompleteFlagOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</template>
<template v-else-if="item.prop === 'sentStatus'">
<el-select v-model="scope.row[item.prop]"
placeholder="请选择"
filterable
style="width: 100%"
@change="handleSentStatusChange(scope.row)">
<el-option v-for="item in sentStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select> </el-select>
</el-form-item>
</el-row>
</el-form>
<!-- 数据表格 -->
<el-table :data="tableList"
border
style="width: 100%"
class="table-container">
<el-table-column v-for="item in columns"
:key="item.label"
:prop="item.prop"
:label="item.label"
:width="item.width"
:fixed="item.fixed"
:class-name="item.className">
<template #header="{ column }"
v-if="item.prop === 'receiptPhoto'">
<div class="header-container">
<span>{{ column.label }}</span>
<el-button @click="showPhoto = !showPhoto"
style="margin-left: 10px;">{{ showPhoto ? '隐藏' : '显示' }}图片</el-button>
</div>
</template> </template>
<template #default="scope">
<template v-if="item.prop === 'receiptPhoto'">
<div class="receipt-photo-container"
v-if="showPhoto">
<span v-if="JSON.parse(scope.row[item.prop] || '[]').length === 0">暂无图片</span>
<el-image v-else
v-for="(urlStr, index) in JSON.parse(scope.row[item.prop] || '[]')"
:key="index"
:initial-index="index"
:preview-src-list="JSON.parse(scope.row[item.prop] || '[]')"
preview-teleported
:src="urlStr"
alt="图片"
class="receipt-photo-item"
fit="cover"
style="width: 80px; height: 50px; " />
</div>
</template>
<template v-else-if="item.prop === 'logisticsTrack'">
<el-button type="primary"
@click="handleLogisticsTrack(scope.row)"
text>
查看物流轨迹
</el-button>
</template>
<template v-else-if="item.prop === 'receiptPhotoCompleteFlag'">
<el-select v-model="scope.row[item.prop]"
placeholder="请选择"
style="width: 100%"
@change="handleReceiptPhotoChangeStatus(scope.row)">
<el-option v-for="item in receiptPhotoCompleteFlagOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</template>
<template v-else-if="item.prop === 'sentStatus'">
<el-select v-model="scope.row[item.prop]"
placeholder="请选择"
filterable
style="width: 100%"
@change="handleSentStatusChange(scope.row)">
<el-option v-for="item in sentStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</template>
<template v-else> <template v-else>
<!-- 其他字段显示原始值 --> <!-- 其他字段显示原始值 -->
{{ formatter(scope.row, scope.column, scope.row[item.prop]) }} {{ formatter(scope.row, scope.column, scope.row[item.prop]) }}
</template>
</template> </template>
</template> </el-table-column>
</el-table-column> <!-- <el-table-column label="操作"
<!-- <el-table-column label="操作"
width="200" width="200"
fixed="right"> fixed="right">
<template #default="scope"> <template #default="scope">
...@@ -136,13 +137,14 @@ ...@@ -136,13 +137,14 @@
</el-button> </el-button>
</template> </template>
</el-table-column> --> </el-table-column> -->
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<pagination :total="total" <pagination :total="total"
v-model:page="queryParams.pageNum" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" v-model:limit="queryParams.pageSize"
@pagination="getLogisticsReceiptList" /> @pagination="getLogisticsReceiptList" />
</div> </el-col>
</el-row>
</div> </div>
</template> </template>
...@@ -402,65 +404,78 @@ const handleSentStatusChange = async (row) => { ...@@ -402,65 +404,78 @@ const handleSentStatusChange = async (row) => {
<style scoped <style scoped
lang="scss"> lang="scss">
.table-container { .app-container {
margin-top: 20px; >.el-row {
.el-col {
display: flex;
flex-direction: column;
height: 100%;
.header-container { .table-container {
display: flex; margin-top: 20px;
align-items: center;
}
::v-deep(.el-image) { .header-container {
img { display: flex;
width: 80px !important; align-items: center;
height: 50px !important; }
}
}
}
.receipt-photo-container { ::v-deep(.el-image) {
padding: 0 15px; img {
display: flex; width: 80px !important;
flex-wrap: wrap; height: 50px !important;
gap: 10px; }
min-width: 200px; }
/* justify-content: center; // 内容整体居中 }
align-items: flex-start; // 顶部对齐 */
justify-content: flex-start; // 改为左对齐,让每行都从左边开始
align-items: flex-start; // 顶部对齐
.receipt-photo-item { .receipt-photo-container {
border-radius: 4px; padding: 0 15px;
border: 1px solid #e4e7ed; display: flex;
transition: all 0.3s; flex-wrap: wrap;
flex: 0 0 80px; // 固定宽度,不伸缩 gap: 10px;
min-width: 200px;
/* justify-content: center; // 内容整体居中
align-items: flex-start; // 顶部对齐 */
justify-content: flex-start; // 改为左对齐,让每行都从左边开始
align-items: flex-start; // 顶部对齐
&:hover { .receipt-photo-item {
border-color: #409eff; border-radius: 4px;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2); border: 1px solid #e4e7ed;
} transition: all 0.3s;
} flex: 0 0 80px; // 固定宽度,不伸缩
}
// 让表格列宽自适应内容 &:hover {
::v-deep(.el-table) { border-color: #409eff;
.el-table__body-wrapper { box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
.el-table__body { }
.el-table__row {
.cell {
white-space: nowrap;
overflow: visible;
} }
} }
td.el-table__cell.col-receipt-photo { // 让表格列宽自适应内容
.cell { ::v-deep(.el-table) {
padding-right: 0px; // 给回单照片列补充右内边距 .el-table__body-wrapper {
padding-left: 0px; // 给回单照片列补充左内边距 .el-table__body {
text-align: center; // 内容居中 .el-table__row {
.cell {
white-space: nowrap;
overflow: visible;
}
}
td.el-table__cell.col-receipt-photo {
.cell {
padding-right: 0px; // 给回单照片列补充右内边距
padding-left: 0px; // 给回单照片列补充左内边距
text-align: center; // 内容居中
}
}
}
} }
} }
} }
} }
} }
</style> </style>
...@@ -39,7 +39,7 @@ export default defineConfig(({ mode, command }) => { ...@@ -39,7 +39,7 @@ export default defineConfig(({ mode, command }) => {
rewrite: (p) => p.replace(/^\/ql_local/, '') rewrite: (p) => p.replace(/^\/ql_local/, '')
}, },
'/bc_local': { '/bc_local': {
target: 'http://192.168.100.103:8180', target: 'http://192.168.100.180:8180',
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/bc_local/, '') rewrite: (p) => p.replace(/^\/bc_local/, '')
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论