整页导出功能上线

This commit is contained in:
davy 2025-08-05 14:38:36 +08:00
parent 40cfe0f9ff
commit 5557109499
5 changed files with 308 additions and 29 deletions

View File

@ -1,2 +1,3 @@
# 预发布环境接口地址
VITE_API_URL=https://vue.ruoyi.vip/prod-api
# 开发环境接口地址
VITE_API_URL=http://dev.bar.beerape.com/prod-api
VITE_API_STORE_URL=http://dev.design.beerape.com

BIN
dist.zip Normal file

Binary file not shown.

View File

@ -97,8 +97,8 @@
<layout-tool>
<header-user />
</layout-tool>
<!-- 夜间模式 -->
<layout-tool
<!-- 夜间模式 - 已禁用使用固定默认主题配置 -->
<!-- <layout-tool
ref="darkSwitchRef"
:class="[
'dark-switch',
@ -111,9 +111,9 @@
:model-value="darkMode"
@update:modelValue="updateDarkMode"
/>
</layout-tool>
<!-- 主题设置 -->
<!-- <layout-tool @click="openSetting">
</layout-tool> -->
<!-- 主题设置 - 已禁用使用固定默认主题配置 -->
<!-- <layout-tool @click="openSetting"></layout-tool>
<el-icon>
<MoreOutlined />
</el-icon>
@ -162,7 +162,7 @@
</span>
</template>
</ele-pro-layout>
<!-- 主题设置抽屉 -->
<!-- 主题设置抽屉 - 已禁用使用固定默认主题配置 -->
<!-- <setting-drawer v-model="settingVisible" /> -->
</template>
@ -184,24 +184,24 @@
ReloadOutlined,
ExpandOutlined,
CompressOutlined,
MoreOutlined,
// MoreOutlined,
CloseOutlined,
ArrowLeftOutlined,
ArrowRightOutlined,
MinusCircleOutlined,
CloseCircleOutlined,
MoonOutlined,
SunOutlined
CloseCircleOutlined
// MoonOutlined,
// SunOutlined
} from '@/components/icons';
import { PROJECT_NAME, HOME_PATH, REDIRECT_PATH } from '@/config/setting';
import { doWithTransition } from '@/utils/common';
// import { doWithTransition } from '@/utils/common';
import { useUserStore } from '@/store/modules/user';
import { useThemeStore } from '@/store/modules/theme';
import { useMobileDevice } from '@/utils/use-mobile';
import { usePageTab } from '@/utils/use-page-tab';
import RouterLayout from '@/components/RouterLayout/index.vue';
import HeaderUser from './components/header-user.vue';
import HeaderNotice from './components/header-notice.vue';
// import HeaderNotice from './components/header-notice.vue';
import PageFooter from './components/page-footer.vue';
// import SettingDrawer from './components/setting-drawer.vue';
@ -266,7 +266,7 @@
/** 是否全屏 */
const isFullscreen = ref(false);
/** 是否显示主题设置抽屉 */
/** 是否显示主题设置抽屉 - 已禁用,使用固定默认主题配置 */
// const settingVisible = ref(false);
/** 页签右键菜单 */
@ -396,22 +396,22 @@
}
};
/** 打开主题设置抽屉 */
/** 打开主题设置抽屉 - 已禁用,使用固定默认主题配置 */
// const openSetting = () => {
// settingVisible.value = true;
// };
/** 暗黑主题切换开关 */
const darkSwitchRef = ref(null);
/** 暗黑主题切换开关 - 已禁用,使用固定默认主题配置 */
// const darkSwitchRef = ref(null);
/** 切换暗黑模式 */
const updateDarkMode = (isDark) => {
doWithTransition(
() => themeStore.setValue('darkMode', isDark),
darkSwitchRef.value?.$el?.querySelector?.('.el-switch__action'),
!isDark
);
};
/** 切换暗黑模式 - 已禁用,使用固定默认主题配置 */
// const updateDarkMode = (isDark) => {
// doWithTransition(
// () => themeStore.setValue('darkMode', isDark),
// darkSwitchRef.value?.$el?.querySelector?.('.el-switch__action'),
// !isDark
// );
// };
</script>
<style lang="scss" scoped>

View File

@ -33,11 +33,11 @@ const DEFAULT_STATE = {
/** 是否需要页签栏 */
tabBar: true,
/** 布局类型 */
layout: 'default',
layout: 'top',
/** 侧栏布局类型 */
sidebarLayout: 'default',
/** 顶栏风格 */
headerStyle: 'light',
headerStyle: 'dark',
/** 侧栏风格 */
sidebarStyle: 'dark',
/** 双侧栏二级风格 */
@ -51,7 +51,7 @@ const DEFAULT_STATE = {
/** 是否固定内容区 */
fixedBody: true,
/** 内容区是否撑满 */
fluid: true,
fluid: false,
/** 图标是否置于顶栏 */
logoInHeader: false,
/** 侧栏菜单是否彩色图标 */

View File

@ -0,0 +1,278 @@
<template>
<div class="add-beer-form">
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<!-- 酒款信息展示 -->
<el-card shadow="never" class="beer-info-card">
<template #header>
<h4>选中酒款信息</h4>
</template>
<div class="beer-info" v-if="selectedBeer">
<div class="beer-basic">
<div class="beer-image">
<el-image
:src="selectedBeer.cover || '/images/default-beer.png'"
fit="cover"
style="width: 80px; height: 120px; border-radius: 8px;"
/>
</div>
<div class="beer-details">
<h3>{{ selectedBeer.beerName || selectedBeer.name }}</h3>
<p><strong>品牌:</strong> {{ selectedBeer.brandName || selectedBeer.brand || '未知品牌' }}</p>
<p><strong>风格:</strong> {{ selectedBeer.beerStyles || selectedBeer.style || '未知风格' }}</p>
<p><strong>酒精度:</strong> {{ selectedBeer.beerAbv || selectedBeer.abv }}%</p>
</div>
</div>
</div>
<el-empty v-else description="未选择酒款" />
</el-card>
<!-- 上枪配置 -->
<div class="form-section">
<h4>上枪配置</h4>
<el-form-item label="选择酒头" prop="tapNo" required>
<el-select v-model="form.tapNo" placeholder="请选择要使用的酒头" style="width: 100%">
<el-option
v-for="n in 20"
:key="n"
:label="`${n}号酒头`"
:value="n"
/>
</el-select>
</el-form-item>
<el-form-item label="上枪时间" prop="onTapTime">
<el-date-picker
v-model="form.onTapTime"
type="datetime"
placeholder="选择上枪时间"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="form.remark"
type="textarea"
:rows="3"
placeholder="请输入备注信息(可选)"
/>
</el-form-item>
</div>
<!-- 规格价格配置 -->
<div class="form-section">
<h4>规格价格配置</h4>
<el-table :data="form.specList" style="width: 100%">
<el-table-column label="规格名称" min-width="120">
<template #default="{ row, $index }">
<el-input v-model="row.specName" placeholder="如330ML" />
</template>
</el-table-column>
<el-table-column label="销售价格" min-width="120">
<template #default="{ row, $index }">
<el-input-number
v-model="row.price"
:precision="2"
:min="0"
placeholder="0.00"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template #default="{ $index }">
<el-button
type="danger"
size="small"
@click="removeSpec($index)"
:disabled="form.specList.length <= 1"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 10px;">
<el-button type="primary" plain @click="addSpec">+ 添加规格</el-button>
</div>
</div>
</el-form>
<!-- 操作按钮 -->
<div class="form-actions">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitting">
确认上枪
</el-button>
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { ElMessage } from 'element-plus'
// Props
const props = defineProps({
selectedBeer: {
type: Object,
default: () => null
}
})
// Events
const emit = defineEmits(['submit', 'cancel'])
//
const formRef = ref()
const submitting = ref(false)
const form = reactive({
tapNo: null,
onTapTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
remark: '',
specList: [
{ specName: '330ML', price: 0 },
{ specName: '500ML', price: 0 }
]
})
//
const rules = {
tapNo: [
{ required: true, message: '请选择酒头', trigger: 'change' }
]
}
//
watch(() => props.selectedBeer, (newBeer) => {
if (newBeer) {
//
if (newBeer.specs && newBeer.specs.length > 0) {
form.specList = newBeer.specs.map(spec => ({
specName: spec.name || spec.specName,
price: spec.price || 0
}))
}
}
}, { immediate: true })
//
const addSpec = () => {
form.specList.push({
specName: '',
price: 0
})
}
//
const removeSpec = (index) => {
if (form.specList.length > 1) {
form.specList.splice(index, 1)
}
}
//
const handleSubmit = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
//
const validSpecs = form.specList.filter(spec => spec.specName && spec.price > 0)
if (validSpecs.length === 0) {
ElMessage.warning('请至少添加一个有效的规格价格')
return
}
submitting.value = true
const submitData = {
...form,
specList: validSpecs,
beerId: props.selectedBeer?.id || props.selectedBeer?.beerId,
beerType: props.selectedBeer?.beerType || 'main' // main custom
}
emit('submit', submitData)
} catch (error) {
console.log('表单验证失败:', error)
} finally {
submitting.value = false
}
}
//
const handleCancel = () => {
emit('cancel')
}
</script>
<style scoped>
.add-beer-form {
padding: 20px 0;
}
.beer-info-card {
margin-bottom: 20px;
}
.beer-info {
padding: 10px;
}
.beer-basic {
display: flex;
gap: 15px;
align-items: flex-start;
}
.beer-image {
flex-shrink: 0;
}
.beer-details {
flex: 1;
}
.beer-details h3 {
margin: 0 0 10px 0;
color: #303133;
font-size: 18px;
}
.beer-details p {
margin: 5px 0;
color: #606266;
font-size: 14px;
}
.form-section {
margin-bottom: 20px;
padding: 15px;
background: #fafafa;
border-radius: 8px;
}
.form-section h4 {
margin: 0 0 15px 0;
color: #303133;
font-size: 16px;
font-weight: 600;
}
.form-actions {
text-align: right;
padding-top: 20px;
border-top: 1px solid #ebeef5;
}
.form-actions .el-button {
margin-left: 10px;
}
</style>