会员个人中心页面初步完成
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
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');
|
||||
Reference in New Issue
Block a user