240 lines
7.8 KiB
JavaScript
240 lines
7.8 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const CSS_DIR = path.join(__dirname, '../common/style/memberInfo/pages');
|
|
const STYLE_PREFIX = '@/common/style/memberInfo/pages';
|
|
|
|
const PAGES = {
|
|
booking: {
|
|
cssFile: 'booking-pixso.css',
|
|
pageCssFile: 'booking-page.css',
|
|
rootClass: 'Pixso-frame-2_964',
|
|
backFrameClass: 'Pixso-frame-2_969',
|
|
extraData: `,
|
|
activeTab: 'ongoing'`,
|
|
extraMethods: `,
|
|
switchTab(tab) {
|
|
this.activeTab = tab
|
|
},
|
|
cancelBooking() {
|
|
uni.showModal({
|
|
title: '取消预约',
|
|
content: '确定要取消该预约吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showToast({ title: '已取消', icon: 'success' })
|
|
}
|
|
}
|
|
})
|
|
}`
|
|
},
|
|
memberCard: {
|
|
cssFile: 'member-card-pixso.css',
|
|
pageCssFile: 'member-card-page.css',
|
|
rootClass: 'Pixso-frame-2_877',
|
|
backFrameClass: 'Pixso-frame-2_882',
|
|
extraData: `,
|
|
activeFilter: 'all'`,
|
|
extraMethods: `,
|
|
switchFilter(filter) {
|
|
this.activeFilter = filter
|
|
},
|
|
renewCard() {
|
|
uni.showToast({ title: '续费功能开发中', icon: 'none' })
|
|
}`
|
|
},
|
|
userInfo: {
|
|
cssFile: 'user-info-pixso.css',
|
|
pageCssFile: 'user-info-page.css',
|
|
rootClass: 'Pixso-frame-2_791',
|
|
backFrameClass: 'Pixso-frame-2_796',
|
|
navWrapperClass: 'stroke-wrapper-2_795',
|
|
navContentClass: 'frame-content-2_795',
|
|
navTitleClass: 'Pixso-paragraph-2_799',
|
|
saveFrameClass: 'Pixso-frame-2_800',
|
|
extraData: `,
|
|
name: '张小芳',
|
|
phone: '138****6789',
|
|
gender: 'female',
|
|
birthday: '1995年06月15日',
|
|
height: '165',
|
|
weight: '63.5',
|
|
fitnessGoals: ['增肌']`,
|
|
extraMethods: `,
|
|
handleSave() {
|
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
|
},
|
|
changeAvatar() {
|
|
uni.showToast({ title: '更换头像功能开发中', icon: 'none' })
|
|
},
|
|
rebindPhone() {
|
|
uni.showToast({ title: '换绑功能开发中', icon: 'none' })
|
|
},
|
|
selectGender(gender) {
|
|
this.gender = gender
|
|
},
|
|
toggleGoal(goal) {
|
|
const index = this.fitnessGoals.indexOf(goal)
|
|
if (index >= 0) {
|
|
this.fitnessGoals.splice(index, 1)
|
|
} else {
|
|
this.fitnessGoals.push(goal)
|
|
}
|
|
},
|
|
isGoalSelected(goal) {
|
|
return this.fitnessGoals.includes(goal)
|
|
}`
|
|
}
|
|
};
|
|
|
|
function alignCss(css) {
|
|
let result = css.replace(/@import\s+['"]\.\/base\.css['"];\s*/g, '');
|
|
const replacements = [
|
|
['url(@/assets/images/', 'url(@/static/images/'],
|
|
['box-shadow: 0px 8px 16px 0px rgba(255, 107, 53, 0.25098039215686274)', 'box-shadow: var(--shadow-orange-glow)'],
|
|
['background-color: rgba(255, 255, 255, 1)', 'background-color: var(--bg-white)'],
|
|
['color: rgba(255, 255, 255, 1)', 'color: var(--text-inverse)'],
|
|
['border-color: rgba(255, 255, 255, 1)', 'border-color: var(--bg-white)'],
|
|
['rgba(11, 43, 75, 1)', 'var(--primary-dark)'],
|
|
['rgba(26, 74, 111, 1)', 'var(--primary-deep)'],
|
|
['rgba(255, 107, 53, 1)', 'var(--accent-orange)'],
|
|
['rgba(255, 140, 90, 1)', 'var(--accent-orange-light)'],
|
|
['rgba(249, 250, 254, 1)', 'var(--bg-light)'],
|
|
['rgba(30, 42, 58, 1)', 'var(--text-dark)'],
|
|
['rgba(94, 111, 141, 1)', 'var(--text-muted)'],
|
|
['rgba(138, 153, 180, 1)', 'var(--text-light)'],
|
|
['rgba(233, 237, 242, 1)', 'var(--border-light)'],
|
|
['rgba(46, 204, 113, 1)', 'var(--success-green)'],
|
|
['rgba(231, 76, 60, 1)', 'var(--error-red)'],
|
|
['height: 900px', 'height: auto;\n min-height: 100%'],
|
|
['height: 2300px', 'height: auto;\n min-height: 100%'],
|
|
['height: 1901px', 'height: auto']
|
|
];
|
|
for (const [from, to] of replacements) {
|
|
result = result.split(from).join(to);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function convertTemplate(template, config) {
|
|
let result = template.replace(/\r\n/g, '\n');
|
|
|
|
result = result.replace(/<div\b/g, '<view');
|
|
result = result.replace(/<\/div>/g, '</view>');
|
|
result = result.replace(/<p\b/g, '<text');
|
|
result = result.replace(/<\/p>/g, '</text>');
|
|
result = result.replace(/\s+id="[^"]*"/g, '');
|
|
result = result.replace(/\{\{\s*"([^"]*?)"\s*\}\}/gs, '$1');
|
|
result = result.replace(/\{\{\s*'([^']*?)'\s*\}\}/gs, '$1');
|
|
result = result.replace(
|
|
'<view class="scroll-container">',
|
|
'<view class="scroll-container theme-light">'
|
|
);
|
|
result = result.replace(/>\s*9:41\s*</g, '>{{ statusBarTime }}<');
|
|
|
|
if (config.backFrameClass) {
|
|
result = result.replace(
|
|
new RegExp(`class="${config.backFrameClass}"`, 'g'),
|
|
`class="${config.backFrameClass} nav-back" @tap.stop="goBack"`
|
|
);
|
|
}
|
|
|
|
if (config.navTitleClass) {
|
|
result = result.replace(
|
|
new RegExp(`class="${config.navTitleClass}"`, 'g'),
|
|
`class="${config.navTitleClass} nav-title"`
|
|
);
|
|
}
|
|
|
|
if (config.saveFrameClass) {
|
|
result = result.replace(
|
|
new RegExp(`class="${config.saveFrameClass}"`, 'g'),
|
|
`class="${config.saveFrameClass}" @tap="handleSave"`
|
|
);
|
|
}
|
|
|
|
if (config.bindings) {
|
|
for (const { from, to } of config.bindings) {
|
|
result = result.replace(from, to);
|
|
}
|
|
}
|
|
|
|
return result.trim();
|
|
}
|
|
|
|
function buildPageCss(config) {
|
|
return `@import './sub-page-base.css';
|
|
|
|
.${config.rootClass} {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
`;
|
|
}
|
|
|
|
function convertPage(pageName, config) {
|
|
const vuePath = path.join(__dirname, `../pages/memberInfo/${pageName}.vue`);
|
|
const cssPath = path.join(CSS_DIR, config.cssFile);
|
|
const pageCssPath = path.join(CSS_DIR, config.pageCssFile);
|
|
|
|
const content = fs.readFileSync(vuePath, 'utf8').replace(/\r\n/g, '\n');
|
|
const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
|
|
const styleMatch = content.match(/<style>([\s\S]*?)<\/style>/);
|
|
|
|
if (!templateMatch || !styleMatch) {
|
|
throw new Error(`Could not parse ${pageName}.vue`);
|
|
}
|
|
|
|
const template = convertTemplate(templateMatch[1], config);
|
|
const css = alignCss(styleMatch[1].trim());
|
|
const pageCss = buildPageCss(config);
|
|
|
|
const extraMethods = (config.extraMethods || '').replace(/^\s*,\s*/, '');
|
|
const extraDataBlock = (config.extraData || '').replace(/^\s*,\s*/, '');
|
|
const dataBody = pageName === 'userInfo'
|
|
? '...userInfoMock'
|
|
: extraDataBlock;
|
|
|
|
const vueOutput = `<template>
|
|
${template}
|
|
</template>
|
|
|
|
<script>
|
|
import { statusBarTimeMixin, subPageMixin } from '@/common/memberInfo/mixins.js'${pageName === 'userInfo' ? "\nimport { userInfoMock } from '@/common/memberInfo/mockData.js'" : ''}
|
|
|
|
export default {
|
|
mixins: [statusBarTimeMixin, subPageMixin],
|
|
data() {
|
|
return {
|
|
${dataBody}
|
|
}
|
|
},
|
|
methods: {
|
|
${extraMethods}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
@import '${STYLE_PREFIX}/${config.pageCssFile}';
|
|
@import '${STYLE_PREFIX}/${config.cssFile}';
|
|
</style>
|
|
`;
|
|
|
|
fs.writeFileSync(cssPath, css + '\n', 'utf8');
|
|
fs.writeFileSync(pageCssPath, pageCss, 'utf8');
|
|
fs.writeFileSync(vuePath, vueOutput, 'utf8');
|
|
console.log(`converted ${pageName}.vue -> ${config.cssFile}`);
|
|
}
|
|
|
|
const target = process.argv[2];
|
|
const entries = target
|
|
? [[target, PAGES[target]]].filter(([, config]) => config)
|
|
: Object.entries(PAGES);
|
|
|
|
for (const [pageName, config] of entries) {
|
|
convertPage(pageName, config);
|
|
}
|
|
|
|
console.log('done');
|