This commit is contained in:
biss committed 2026-07-28 15:41:28 +08:00
1 parent a61dacff1a
commit 2dae303cf1
17 files changed
+6796 -90

No files matched your search

+38
View File
@@ -9,7 +9,9 @@
"version": "0.0.0",
"dependencies": {
"@capacitor/android": "^8.4.2",
"@capacitor/barcode-scanner": "^3.1.0",
"@capacitor/core": "^8.4.2",
"@capacitor/geolocation": "^8.2.0",
"@capacitor/ios": "^8.4.2",
"@ckeditor/ckeditor5-vue": "^8.2.0",
"@element-plus/icons-vue": "^2.3.2",
@@ -102,6 +104,18 @@
"@capacitor/core": "^8.4.0"
}
},
"node_modules/@capacitor/barcode-scanner": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@capacitor/barcode-scanner/-/barcode-scanner-3.1.0.tgz",
"integrity": "sha512-uE4njvsQGVfhjChg5ZU8ayYX9i2LM9Dg9/TWXG/L1s+pRVR5JG6PxsC3dCuKa9F6OVCYrKcEmdSi3E6KT+fMbg==",
"license": "MIT",
"dependencies": {
"html5-qrcode": "2.3.8"
},
"peerDependencies": {
"@capacitor/core": ">=8.0.0"
}
},
"node_modules/@capacitor/cli": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.4.2.tgz",
@@ -144,6 +158,18 @@
"tslib": "^2.1.0"
}
},
"node_modules/@capacitor/geolocation": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@capacitor/geolocation/-/geolocation-8.2.0.tgz",
"integrity": "sha512-N29QcoIPmme0xSxRkm7+3hjoHp6mBAOarxecvtCCZKyOBeKiJsFUq981cezg2XWBa6fhCXJMCCjQPngKK/dIag==",
"license": "MIT",
"dependencies": {
"@capacitor/synapse": "^1.0.4"
},
"peerDependencies": {
"@capacitor/core": ">=8.0.0"
}
},
"node_modules/@capacitor/ios": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.4.2.tgz",
@@ -153,6 +179,12 @@
"@capacitor/core": "^8.4.0"
}
},
"node_modules/@capacitor/synapse": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@capacitor/synapse/-/synapse-1.0.4.tgz",
"integrity": "sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==",
"license": "ISC"
},
"node_modules/@ckeditor/ckeditor5-adapter-ckfinder": {
"version": "48.3.1",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-48.3.1.tgz",
@@ -3405,6 +3437,12 @@
"node": ">=8.0.0"
}
},
"node_modules/html5-qrcode": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/html5-qrcode/-/html5-qrcode-2.3.8.tgz",
"integrity": "sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==",
"license": "Apache-2.0"
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+4 -1
View File
@@ -8,7 +8,8 @@
"build": "vue-tsc -b && vite build",
"build:capacitor": "vue-tsc -b && vite build --mode capacitor",
"preview": "vite preview",
"cap:sync": "npx cap sync",
"cap:configure": "node scripts/configure-capacitor.mjs",
"cap:sync": "npx cap sync && npm run cap:configure",
"cap:open:android": "npx cap open android",
"cap:open:ios": "npx cap open ios",
"cap:run:android": "npx cap run android",
@@ -16,7 +17,9 @@
},
"dependencies": {
"@capacitor/android": "^8.4.2",
"@capacitor/barcode-scanner": "^3.1.0",
"@capacitor/core": "^8.4.2",
"@capacitor/geolocation": "^8.2.0",
"@capacitor/ios": "^8.4.2",
"@ckeditor/ckeditor5-vue": "^8.2.0",
"@element-plus/icons-vue": "^2.3.2",
+81
View File
@@ -0,0 +1,81 @@
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const webRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
function updateFile(path, update) {
if (!existsSync(path)) return false
const current = readFileSync(path, 'utf8')
const next = update(current)
if (next !== current) writeFileSync(path, next, 'utf8')
return true
}
function configureAndroid() {
const variablesPath = resolve(webRoot, 'android', 'variables.gradle')
const manifestPath = resolve(
webRoot,
'android',
'app',
'src',
'main',
'AndroidManifest.xml',
)
if (!existsSync(variablesPath) || !existsSync(manifestPath)) return false
updateFile(variablesPath, content => {
if (!/minSdkVersion\s*=\s*\d+/.test(content)) {
throw new Error('未在 android/variables.gradle 中找到 minSdkVersion。')
}
return content.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 26')
})
updateFile(manifestPath, content => {
const declarations = [
'<uses-permission android:name="android.permission.CAMERA" />',
'<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />',
'<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />',
'<uses-feature android:name="android.hardware.camera" android:required="false" />',
'<uses-feature android:name="android.hardware.location.gps" android:required="false" />',
]
const missing = declarations.filter(declaration => !content.includes(declaration))
if (!missing.length) return content
return content.replace(
'</manifest>',
` ${missing.join('\n ')}\n</manifest>`,
)
})
return true
}
function configureIos() {
const infoPlistPath = resolve(webRoot, 'ios', 'App', 'App', 'Info.plist')
if (!existsSync(infoPlistPath)) return false
updateFile(infoPlistPath, content => {
const descriptions = [
['NSCameraUsageDescription', '用于扫描教师展示的课堂签到二维码。'],
['NSLocationWhenInUseUsageDescription', '用于在课堂签到时校验当前位置。'],
['NSLocationAlwaysAndWhenInUseUsageDescription', '用于在课堂签到时校验当前位置。'],
]
const missing = descriptions.filter(([key]) => !content.includes(`<key>${key}</key>`))
if (!missing.length) return content
const entries = missing
.map(([key, value]) => `\t<key>${key}</key>\n\t<string>${value}</string>`)
.join('\n')
return content.replace('</dict>', `${entries}\n</dict>`)
})
return true
}
const configuredPlatforms = [
configureAndroid() ? 'Android' : null,
configureIos() ? 'iOS' : null,
].filter(Boolean)
if (!configuredPlatforms.length) {
throw new Error('尚未生成 Capacitor 原生工程,请先运行 npx cap add android 或 ios。')
}
console.log(`已配置 ${configuredPlatforms.join('、')} 的扫码和定位权限。`)
Loaded 3 of 17 files, more files were not shown because too many files have changed in this diff. Show more