This commit is contained in:
张成
2026-04-28 18:11:17 +08:00
parent 335a513571
commit 9c233e5281
10 changed files with 100 additions and 81 deletions

2
.env.development Normal file
View File

@@ -0,0 +1,2 @@
VUE_APP_IMAGE_BASE=
VUE_APP_IMAGE_VERSION=dev

2
.env.production Normal file
View File

@@ -0,0 +1,2 @@
VUE_APP_IMAGE_BASE=https://bimwe.oss-cn-shanghai.aliyuncs.com/web
VUE_APP_IMAGE_VERSION=20260428

BIN
public/foundry_1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

View File

@@ -6,7 +6,7 @@
<div class="footer-main">
<div class="footer-section">
<div class="footer-logo">
<img :src="require('@/assets/img/logo.png')" alt="丙维科技" class="logo">
<img :src="img('logo.svg')" alt="丙维科技" class="logo">
<h3>上海丙维数字科技有限公司</h3>
<p class="company-desc">AI 工程交付与企业数字化服务</p>
<router-link to="/index#contact" class="footer-cta">预约咨询</router-link>
@@ -80,6 +80,7 @@
<script>
import { getFooterSolutionsMenu } from '../config/menu'
import { img } from '@/utils/image'
export default {
name: 'ifooter',
@@ -91,6 +92,7 @@ export default {
data() {
const icon = (path) => `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">${path}</svg>`
return {
img,
showBackToTop: false,
solutionsMenu: getFooterSolutionsMenu(),
icons: {

View File

@@ -109,6 +109,7 @@
<script>
import { getMainMenu } from '../config/menu'
import { img } from '@/utils/image'
export default {
name: 'ihead',
@@ -123,10 +124,10 @@ export default {
computed: {
image_paths() {
return {
logo: require('@/assets/img/logo.png'),
mobile_logo: require('@/assets/img/logo.png'),
hamburger: require('@/assets/img/svg/ic-hamburger.svg'),
arrow_back: require('@/assets/img/svg/ic-arrow-back.svg')
logo: img('logo.svg'),
mobile_logo: img('logo.svg'),
hamburger: img('svg/ic-hamburger.svg'),
arrow_back: img('svg/ic-arrow-back.svg')
}
}
},

35
src/utils/image.js Normal file
View File

@@ -0,0 +1,35 @@
const normalizeBase = (base) => {
if (!base) return ''
return base.endsWith('/') ? base.slice(0, -1) : base
}
const DEFAULT_IMAGE_BASE = 'https://bimwe.oss-cn-shanghai.aliyuncs.com/web'
const IS_DEV = process.env.NODE_ENV === 'development'
const IMAGE_BASE = normalizeBase(process.env.VUE_APP_IMAGE_BASE || (IS_DEV ? '' : DEFAULT_IMAGE_BASE))
const IMAGE_VERSION = process.env.VUE_APP_IMAGE_VERSION || ''
const localImages = IS_DEV
? require.context('@/assets/img', true, /\.(png|jpe?g|gif|webp|svg)$/i)
: null
const isVersionTarget = (url) => /\.(png|jpe?g)(\?.*)?$/i.test(url)
const appendVersion = (url) => {
if (!IMAGE_VERSION) return url
// data/blob URLs cannot carry query strings safely.
if (typeof url === 'string' && (url.startsWith('data:') || url.startsWith('blob:'))) return url
if (!isVersionTarget(url)) return url
return url.includes('?') ? `${url}&v=${IMAGE_VERSION}` : `${url}?v=${IMAGE_VERSION}`
}
export const img = (name) => {
const cleanName = String(name || '').replace(/^\/+/, '')
if (IS_DEV && !IMAGE_BASE && localImages) {
try {
return appendVersion(localImages(`./${cleanName}`))
} catch (e) {
return appendVersion(`/${cleanName}`)
}
}
return appendVersion(`${IMAGE_BASE}/${cleanName}`)
}

View File

@@ -79,7 +79,7 @@
aria-label="滚动到解决方案"
@click="scrollToProducts"
>
<img src="../assets/img/svg/ic-caret.svg" alt="" aria-hidden="true">
<img :src="img('svg/ic-caret.svg')" alt="" aria-hidden="true">
</button>
</div>
@@ -208,24 +208,24 @@
<script>
import ResponsiveHelper from '../static/responsive_helper'
import { img } from '@/utils/image'
let banner_index0 = require('../assets/img/banner-index0.png')
let banner_index1 = require('../assets/img/banner-index1.png')
let banner_index2 = require('../assets/img/banner-index2.png')
let banner_index3 = require('../assets/img/banner-index3.png')
const banner_index0 = img('banner-index0.png')
const banner_index1 = img('banner-index1.png')
const banner_index2 = img('banner-index2.png')
const banner_index3 = img('banner-index3.png')
let boxbg_cleaning = require('../assets/img/boxbg-cleaning.png')
let boxbg_smartbuildings = require('../assets/img/boxbg-smartbuildings.png')
let boxbg_iot = require('../assets/img/boxbg-iot.png')
let boxbg_facilitiesmanagement = require('../assets/img/boxbg-facilitiesmanagement.png')
let solution_app_delivery = require('../assets/img/solution-app-delivery.svg')
let solution_mini_program = require('../assets/img/solution-mini-program.svg')
const boxbg_cleaning = img('boxbg-cleaning.png')
const boxbg_smartbuildings = img('boxbg-smartbuildings.png')
const boxbg_iot = img('boxbg-iot.png')
const boxbg_facilitiesmanagement = img('boxbg-facilitiesmanagement.png')
const solution_app_delivery = img('solution-app-delivery.svg')
const solution_mini_program = img('solution-mini-program.svg')
const partnerLogosContext = require.context('../assets/img/hezuo', false, /\.(png|jpe?g|webp|svg)$/i)
const partnerLogos = partnerLogosContext
.keys()
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))
.map((key) => ({ logo: partnerLogosContext(key) }))
const partnerLogos = Array.from({ length: 27 }, (_, index) => {
const num = String(index + 1).padStart(2, '0')
return { logo: img(`hezuo/client-${num}.png`) }
})
export default {
@@ -249,6 +249,7 @@ export default {
}
return {
img,
icons,
swiperOption: {
autoplay: {

View File

@@ -4,7 +4,7 @@
<section class="page-banner">
<div class="gif-banner" aria-hidden="true">
<img src="https://bimwe.oss-cn-shanghai.aliyuncs.com/web/foundry_1.gif" alt="" class="banner-gif">
<img src="/foundry_1.gif" alt="" class="banner-gif">
</div>
<div class="container banner-content">
<h1 class="banner-title">解决方案</h1>

View File

@@ -1,37 +1,39 @@
import aiWorkflowHero from '@/assets/img/ai-workflow-hero.jpg'
import aiDashboardCard from '@/assets/img/ai-dashboard-card.png'
import financeTrading from '@/assets/img/finance-trading-660x370.png'
import reinventingGraphics from '@/assets/img/reinventing-modern-graphics-fallback.jpg'
import { img } from '@/utils/image'
import estateHero from '@/assets/img/like-no-place-youve-ever-worked.jpg'
import estateScene1 from '@/assets/img/boxbg-propertyandrealestate.jpg'
import estateScene2 from '@/assets/img/banner-page-about-us-mobile.jpg'
import estateScene3 from '@/assets/img/smart-city-network.png'
const aiWorkflowHero = img('ai-workflow-hero.jpg')
const aiDashboardCard = img('ai-dashboard-card.png')
const financeTrading = img('finance-trading-660x370.png')
const reinventingGraphics = img('reinventing-modern-graphics-fallback.jpg')
import iotHero from '@/assets/img/driving-automotive-growth-fallback.jpg'
import iotScene1 from '@/assets/img/iot1.jpg'
import iotScene2 from '@/assets/img/iot2.jpg'
import iotScene3 from '@/assets/img/boxbg-iot.png'
const estateHero = img('like-no-place-youve-ever-worked.jpg')
const estateScene1 = img('boxbg-propertyandrealestate.jpg')
const estateScene2 = img('banner-page-about-us-mobile.jpg')
const estateScene3 = img('smart-city-network.png')
import facilityHero from '@/assets/img/supercharging-healthcare-fallback.jpg'
import facilityScene1 from '@/assets/img/boxbg-facilitiesmanagement.png'
import facilityScene2 from '@/assets/img/boxbg-smartbuildings.png'
import facilityScene3 from '@/assets/img/chatgpt-image-2026-4-27-15-12-15.png'
const iotHero = img('driving-automotive-growth-fallback.jpg')
const iotScene1 = img('iot1.jpg')
const iotScene2 = img('iot2.jpg')
const iotScene3 = img('boxbg-iot.png')
import integrationHero from '@/assets/img/integration-platform-hero.jpg'
import integrationScene1 from '@/assets/img/boxbg-errands.png'
import integrationScene2 from '@/assets/img/banner-index2.png'
import integrationScene3 from '@/assets/img/banner-index3.png'
const facilityHero = img('supercharging-healthcare-fallback.jpg')
const facilityScene1 = img('boxbg-facilitiesmanagement.png')
const facilityScene2 = img('boxbg-smartbuildings.png')
const facilityScene3 = img('chatgpt-image-2026-4-27-15-12-15.png')
import appHero from '@/assets/img/app-delivery-flow.png'
import appScene1 from '@/assets/img/chatgpt-image-2026-4-27-15-26-26.png'
import appScene2 from '@/assets/img/chatgpt-image-2026-4-27-15-26-22.png'
import appScene3 from '@/assets/img/chatgpt-image-2026-4-27-15-25-58.png'
const integrationHero = img('integration-platform-hero.jpg')
const integrationScene1 = img('boxbg-errands.png')
const integrationScene2 = img('banner-index2.png')
const integrationScene3 = img('banner-index3.png')
import miniHero from '@/assets/img/mini-program-growth-hero.jpg'
import miniScene1 from '@/assets/img/banner-index1-mobile.jpg'
import miniScene2 from '@/assets/img/chatgpt-image-2026-4-27-15-26-06.png'
import miniScene3 from '@/assets/img/chatgpt-image-2026-4-27-15-26-14.png'
const appHero = img('app-delivery-flow.png')
const appScene1 = img('chatgpt-image-2026-4-27-15-26-26.png')
const appScene2 = img('chatgpt-image-2026-4-27-15-26-22.png')
const appScene3 = img('chatgpt-image-2026-4-27-15-25-58.png')
const miniHero = img('mini-program-growth-hero.jpg')
const miniScene1 = img('banner-index1-mobile.jpg')
const miniScene2 = img('chatgpt-image-2026-4-27-15-26-06.png')
const miniScene3 = img('chatgpt-image-2026-4-27-15-26-14.png')
export const solutionImageMap = {
aiSolutions: {

View File

@@ -8,7 +8,6 @@ const resolve = (dir) => {
const BASE_URL = process.env.NODE_ENV === "development" ? "/" : "/";
const sourceMap = process.env.NODE_ENV === "development";
const ResponsiveLoaderSharp = require('responsive-loader/sharp');
module.exports = {
publicPath: BASE_URL,
lintOnSave: false, // 是否启用 eslint
@@ -27,7 +26,8 @@ module.exports = {
.use('file-loader')
.loader('file-loader')
.options({
name: 'assets/svg/[name].[hash:8].[ext]'
context: resolve('src/assets/img'),
name: 'images/[path][name].[ext]'
});
// 普通图片处理(排除 SVG
@@ -38,37 +38,11 @@ module.exports = {
.options({
limit: 10000,
esModule: false,
outputPath: "images/"
outputPath: "images/",
context: resolve('src/assets/img'),
name: '[path][name].[ext]'
});
// 图片压缩
config.module.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
bypassOnDebug: true,
mozjpeg: { progressive: true, quality: 60 },
optipng: { enabled: false },
pngquant: { quality: [0.5, 0.6], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
});
// config.module.rule('responsive-images')
// .test(/\.(png|jpe?g|gif)$/i)
// .use('responsive-loader')
// .loader('responsive-loader')
// .options({
// adapter: ResponsiveLoaderSharp,
// sizes: [1200, 1920], // 超过宽度会生成缩小版本
// quality: 75,
// name: 'images/[name]-[width].[ext]',
// placeholder: false
// });
},
configureWebpack: {