mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-06-21 17:30:13 +08:00
refactor:项目升级Vue3+uView Plus
- 改造入口文件、全量替换组件引入 - 过滤器迁移混入,更新忽略配置,新增迁移文档
This commit is contained in:
39
scripts/migrate-filters-usage.js
Normal file
39
scripts/migrate-filters-usage.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const root = path.join(__dirname, '..')
|
||||
|
||||
function walk(dir, files = []) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (['node_modules', 'uview-ui', '.git', 'scripts'].includes(entry.name)) continue
|
||||
const full = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) walk(full, files)
|
||||
else if (entry.name.endsWith('.vue') || entry.name.endsWith('.js')) files.push(full)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
function process(content) {
|
||||
let result = content
|
||||
result = result.replace(/\$options\.filters\.([a-zA-Z][a-zA-Z0-9_]*)/g, '$1')
|
||||
result = result.replace(/this\.([a-zA-Z][a-zA-Z0-9_]*)\(\)/g, (m, name) => {
|
||||
const filterNames = ['isLogin', 'tipsToLogin', 'forceLogin', 'quiteLoginOut', 'logoff', 'navigateToLogin', 'talkIm', 'callPhone', 'unitPrice', 'goodsFormatPrice']
|
||||
if (filterNames.includes(name) && result.includes(`this.${name}(`)) return m
|
||||
return m
|
||||
})
|
||||
result = result.replace(/([a-zA-Z0-9_.\[\]'"\s]+)\s\|\s(refundWayFilter|accountTypeFilter|statusFilter|paymentTypeFilter)/g, (_, expr, name) => {
|
||||
return `${name}(${expr.trim()})`
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
walk(root).forEach((file) => {
|
||||
const original = fs.readFileSync(file, 'utf8')
|
||||
const updated = process(original)
|
||||
if (updated !== original) {
|
||||
fs.writeFileSync(file, updated)
|
||||
console.log('updated', path.relative(root, file))
|
||||
}
|
||||
})
|
||||
|
||||
console.log('done')
|
||||
51
scripts/migrate-navbar-props.js
Normal file
51
scripts/migrate-navbar-props.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const root = path.join(__dirname, '..')
|
||||
|
||||
function walk(dir, files = []) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (['node_modules', '.git', 'scripts'].includes(entry.name)) continue
|
||||
const full = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) walk(full, files)
|
||||
else if (entry.name.endsWith('.vue')) files.push(full)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
function fixNavbarLine(line) {
|
||||
if (!line.includes('u-navbar')) return line
|
||||
let result = line
|
||||
result = result.replace(/:border-bottom="false"/g, ':border="false"')
|
||||
result = result.replace(/:is-back="/g, ':auto-back="')
|
||||
result = result.replace(/:custom-back="back"/g, ':auto-back="false" @leftClick="back"')
|
||||
result = result.replace(/back-icon-color="/g, 'left-icon-color="')
|
||||
result = result.replace(/:background="navbarOnlyBack"/g, ':bg-color="navbarOnlyBack.background"')
|
||||
result = result.replace(/:background="navbar"/g, ':bg-color="navbar.background"')
|
||||
result = result.replace(/:background="navObj"/g, ':bg-color="navObj.background"')
|
||||
result = result.replace(/:background="background"/g, ':bg-color="background.backgroundColor"')
|
||||
return result
|
||||
}
|
||||
|
||||
function fixCellLine(line) {
|
||||
if (!line.includes('u-cell') || !line.includes(':border-bottom')) return line
|
||||
return line.replace(/:border-bottom="false"/g, ':border="false"')
|
||||
}
|
||||
|
||||
function fixInputLine(line) {
|
||||
if (!line.includes('u-input') || !line.includes(':border-bottom')) return line
|
||||
return line.replace(/:border-bottom="false"/g, 'border="none"')
|
||||
}
|
||||
|
||||
function processFile(file) {
|
||||
const lines = fs.readFileSync(file, 'utf8').split('\n')
|
||||
const updated = lines.map((line) => fixInputLine(fixCellLine(fixNavbarLine(line)))).join('\n')
|
||||
const original = lines.join('\n')
|
||||
if (updated !== original) {
|
||||
fs.writeFileSync(file, updated)
|
||||
console.log('updated', path.relative(root, file))
|
||||
}
|
||||
}
|
||||
|
||||
walk(root).forEach(processFile)
|
||||
console.log('navbar props migration done')
|
||||
33
scripts/migrate-uview-components.js
Normal file
33
scripts/migrate-uview-components.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const root = path.join(__dirname, '..')
|
||||
|
||||
function walk(dir, files = []) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (['node_modules', '.git', 'scripts'].includes(entry.name)) continue
|
||||
const full = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) walk(full, files)
|
||||
else if (entry.name.endsWith('.vue')) files.push(full)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
function process(content) {
|
||||
return content
|
||||
.replace(/u-verification-code/g, 'u-code')
|
||||
.replace(/<u-cell-item/g, '<u-cell')
|
||||
.replace(/<\/u-cell-item>/g, '</u-cell>')
|
||||
.replace(/:arrow="false"/g, ':isLink="false"')
|
||||
}
|
||||
|
||||
walk(root).forEach((file) => {
|
||||
const original = fs.readFileSync(file, 'utf8')
|
||||
const updated = process(original)
|
||||
if (updated !== original) {
|
||||
fs.writeFileSync(file, updated)
|
||||
console.log('updated', path.relative(root, file))
|
||||
}
|
||||
})
|
||||
|
||||
console.log('uview component aliases updated')
|
||||
145
scripts/migrate-vue3.js
Normal file
145
scripts/migrate-vue3.js
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Vue 3 migration helpers for template and script patterns.
|
||||
*/
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const root = path.join(__dirname, '..')
|
||||
const filterNames = [
|
||||
'unitPrice',
|
||||
'goodsFormatPrice',
|
||||
'secrecyMobile',
|
||||
'unixToDate',
|
||||
'beautifyTime',
|
||||
'formatTime',
|
||||
'orderStatusList',
|
||||
'serviceStatusList',
|
||||
'noPassByName',
|
||||
'setClipboard',
|
||||
'clearStrComma'
|
||||
]
|
||||
|
||||
function walk(dir, files = []) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.name === 'node_modules' || entry.name === 'uview-ui' || entry.name === '.git') continue
|
||||
const full = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) walk(full, files)
|
||||
else if (entry.name.endsWith('.vue')) files.push(full)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
function convertFilterPipes(content) {
|
||||
let result = content
|
||||
for (const name of filterNames) {
|
||||
const re = new RegExp(`([\\w\\[\\].'"()\\s]+?)\\s\\|\\s${name}(\\([^)]*\\))?`, 'g')
|
||||
result = result.replace(re, (_, expr, args = '') => {
|
||||
const trimmed = expr.trim()
|
||||
return `${name}(${trimmed}${args ? args.slice(1, -1) ? ', ' + args.slice(1, -1) : '' : ''})`
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function convertComponentFilters(content) {
|
||||
return content.replace(/\|\s*([a-zA-Z][a-zA-Z0-9_]*)(\([^)]*\))?/g, (match, name, args = '') => {
|
||||
if (filterNames.includes(name)) return match
|
||||
return match
|
||||
})
|
||||
}
|
||||
|
||||
function convertPopupVModel(content) {
|
||||
const tags = ['u-popup', 'u-modal', 'u-action-sheet', 'u-picker', 'u-select', 'u-keyboard', 'u-calendar']
|
||||
let result = content
|
||||
for (const tag of tags) {
|
||||
result = result.replace(new RegExp(`(<${tag}[^>]*?)\\bv-model="([^"]+)"`, 'g'), '$1v-model:show="$2"')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function convertNavbarProps(content) {
|
||||
return content
|
||||
.replace(/:is-back="false"/g, ':auto-back="false"')
|
||||
.replace(/:isBack="false"/g, ':auto-back="false"')
|
||||
.replace(/:is-back="true"/g, ':auto-back="true"')
|
||||
.replace(/:isBack="true"/g, ':auto-back="true"')
|
||||
}
|
||||
|
||||
function convertSlotSyntax(content) {
|
||||
let result = content
|
||||
result = result.replace(/\sslot="right-icon"/g, ' #right-icon')
|
||||
result = result.replace(/\sslot="loading"/g, ' #loading')
|
||||
result = result.replace(/\sslot="([^"]+)"/g, ' #$1')
|
||||
result = result.replace(/slot-scope="([^"]+)"/g, '#default="$1"')
|
||||
return result
|
||||
}
|
||||
|
||||
function convertSetDelete(content) {
|
||||
return content
|
||||
.replace(/this\.\$set\(([^,]+),\s*([^,]+),\s*([^)]+)\)/g, '$1[$2] = $3')
|
||||
.replace(/this\.\$delete\(([^,]+),\s*([^)]+)\)/g, 'delete $1[$2]')
|
||||
}
|
||||
|
||||
function moveLocalFiltersToMethods(content) {
|
||||
const match = content.match(/filters:\s*\{([\s\S]*?)\n\s*\},/)
|
||||
if (!match) return content
|
||||
const filtersBlock = match[1]
|
||||
const methodEntries = []
|
||||
const re = /([a-zA-Z][a-zA-Z0-9_]*)\s*\(([^)]*)\)\s*\{([\s\S]*?)\n\s*\},/g
|
||||
let m
|
||||
while ((m = re.exec(filtersBlock + ',')) !== null) {
|
||||
methodEntries.push(` ${m[1]}(${m[2]}) {${m[3]}\n },`)
|
||||
}
|
||||
if (!methodEntries.length) return content
|
||||
|
||||
let updated = content.replace(/filters:\s*\{[\s\S]*?\n\s*\},\n?/, '')
|
||||
updated = convertComponentFiltersInTemplate(updated, methodEntries.map(e => e.trim().split('(')[0].trim()))
|
||||
|
||||
if (updated.includes('methods: {')) {
|
||||
updated = updated.replace('methods: {', `methods: {\n${methodEntries.join('\n')}`)
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
function convertComponentFiltersInTemplate(content, localNames) {
|
||||
let result = content
|
||||
for (const name of localNames) {
|
||||
const clean = name.replace(/^\s+/, '')
|
||||
const re = new RegExp(`([\\w\\[\\].'"()\\s]+?)\\s\\|\\s${clean}(\\([^)]*\\))?`, 'g')
|
||||
result = result.replace(re, (_, expr, args = '') => {
|
||||
const trimmed = expr.trim()
|
||||
const argText = args ? args.slice(1, -1) : ''
|
||||
return `${clean}(${trimmed}${argText ? ', ' + argText : ''})`
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function fixShareComponent(content) {
|
||||
return content
|
||||
.replace(/import mpShare from "uview-ui\/libs\/mixin\/mpShare.js";/, 'import mpShare from "@/utils/mpShare.js";')
|
||||
.replace(/this\.\$options\.filters\.setClipboard\(([^)]+)\)/g, 'setClipboard($1)')
|
||||
}
|
||||
|
||||
function processFile(file) {
|
||||
let content = fs.readFileSync(file, 'utf8')
|
||||
const original = content
|
||||
content = convertFilterPipes(content)
|
||||
content = convertPopupVModel(content)
|
||||
content = convertNavbarProps(content)
|
||||
content = convertSlotSyntax(content)
|
||||
content = convertSetDelete(content)
|
||||
content = moveLocalFiltersToMethods(content)
|
||||
content = fixShareComponent(content)
|
||||
content = content.replace(/import uFormItem from "@\/uview-ui\/components\/u-form-item\/u-form-item.vue";?\n?/g, '')
|
||||
content = content.replace(/import uImage from "@\/uview-ui\/components\/u-image\/u-image.vue";?\n?/g, '')
|
||||
content = content.replace(/components:\s*\{\s*uFormItem,?\s*\},?\n?/g, '')
|
||||
content = content.replace(/components:\s*\{\s*uImage,?\s*\},?\n?/g, '')
|
||||
if (content !== original) {
|
||||
fs.writeFileSync(file, content)
|
||||
console.log('updated', path.relative(root, file))
|
||||
}
|
||||
}
|
||||
|
||||
walk(root).forEach(processFile)
|
||||
console.log('migration complete')
|
||||
Reference in New Issue
Block a user