From fbab15dd2cd2340e66db3c126f2fcb7308fdc20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=86=8A=E7=86=8A=E7=86=8A=E5=AD=90=E8=B7=AF?= Date: Fri, 9 Jan 2026 09:35:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8F=90=E4=BA=A4=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 8 + .gitattributes | 1 + .gitignore | 58 + .npmrc | 5 + .prettierignore | 12 + .prettierrc.json | 20 + eslint.config.ts | 63 + miniprogram/api/login.ts | 31 + miniprogram/api/types.ts | 8 + miniprogram/app.json | 14 + miniprogram/app.scss | 18 + miniprogram/app.ts | 5 + miniprogram/pages/date/date.json | 3 + miniprogram/pages/date/date.scss | 97 + miniprogram/pages/date/date.ts | 204 + miniprogram/pages/date/date.wxml | 74 + miniprogram/pages/index/index.json | 3 + miniprogram/pages/index/index.scss | 133 + miniprogram/pages/index/index.ts | 301 + miniprogram/pages/index/index.wxml | 104 + miniprogram/pages/login/login.json | 9 + miniprogram/pages/login/login.scss | 142 + miniprogram/pages/login/login.ts | 133 + miniprogram/pages/login/login.wxml | 36 + miniprogram/sitemap.json | 9 + miniprogram/utils/aes.ts | 233 + miniprogram/utils/request.ts | 238 + miniprogram/utils/util.ts | 126 + package-lock.json | 1687 + package.json | 30 + project.config.json | 53 + tsconfig.json | 25 + typings/index.d.ts | 10 + typings/npm.d.ts | 27 + typings/types/index.d.ts | 1 + typings/types/wx/index.d.ts | 163 + typings/types/wx/lib.wx.api.d.ts | 38509 +++++++++++++++++++++++ typings/types/wx/lib.wx.app.d.ts | 424 + typings/types/wx/lib.wx.behavior.d.ts | 85 + typings/types/wx/lib.wx.canvas.d.ts | 2623 ++ typings/types/wx/lib.wx.cloud.d.ts | 1155 + typings/types/wx/lib.wx.component.d.ts | 785 + typings/types/wx/lib.wx.event.d.ts | 1436 + typings/types/wx/lib.wx.page.d.ts | 299 + typings/types/wx/lib.wx.phys3D.d.ts | 409 + typings/types/wx/lib.wx.wasm.d.ts | 152 + typings/types/wx/lib.wx.xr-frame.d.ts | 16375 ++++++++++ 47 files changed, 66336 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 eslint.config.ts create mode 100644 miniprogram/api/login.ts create mode 100644 miniprogram/api/types.ts create mode 100644 miniprogram/app.json create mode 100644 miniprogram/app.scss create mode 100644 miniprogram/app.ts create mode 100644 miniprogram/pages/date/date.json create mode 100644 miniprogram/pages/date/date.scss create mode 100644 miniprogram/pages/date/date.ts create mode 100644 miniprogram/pages/date/date.wxml create mode 100644 miniprogram/pages/index/index.json create mode 100644 miniprogram/pages/index/index.scss create mode 100644 miniprogram/pages/index/index.ts create mode 100644 miniprogram/pages/index/index.wxml create mode 100644 miniprogram/pages/login/login.json create mode 100644 miniprogram/pages/login/login.scss create mode 100644 miniprogram/pages/login/login.ts create mode 100644 miniprogram/pages/login/login.wxml create mode 100644 miniprogram/sitemap.json create mode 100644 miniprogram/utils/aes.ts create mode 100644 miniprogram/utils/request.ts create mode 100644 miniprogram/utils/util.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 project.config.json create mode 100644 tsconfig.json create mode 100644 typings/index.d.ts create mode 100644 typings/npm.d.ts create mode 100644 typings/types/index.d.ts create mode 100644 typings/types/wx/index.d.ts create mode 100644 typings/types/wx/lib.wx.api.d.ts create mode 100644 typings/types/wx/lib.wx.app.d.ts create mode 100644 typings/types/wx/lib.wx.behavior.d.ts create mode 100644 typings/types/wx/lib.wx.canvas.d.ts create mode 100644 typings/types/wx/lib.wx.cloud.d.ts create mode 100644 typings/types/wx/lib.wx.component.d.ts create mode 100644 typings/types/wx/lib.wx.event.d.ts create mode 100644 typings/types/wx/lib.wx.page.d.ts create mode 100644 typings/types/wx/lib.wx.phys3D.d.ts create mode 100644 typings/types/wx/lib.wx.wasm.d.ts create mode 100644 typings/types/wx/lib.wx.xr-frame.d.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3b510aa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf +max_line_length = 100 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7f0ebc --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Dependencies +node_modules + +# Build outputs +dist +dist-ssr +coverage +*.local + +# TypeScript +*.tsbuildinfo + +# ESLint +.eslintcache + +# OS +.DS_Store +Thumbs.db + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# WeChat MiniProgram +# npm 构建产物(通过微信开发者工具构建 npm 后生成) +miniprogram/miniprogram_npm/ + +# 微信开发者工具私有配置文件(包含个人开发环境配置) +project.private.config.json + +# 微信开发者工具临时文件 +*.wxapkg +*.wxss.map +*.wxml.map +*.js.map + +# Testing +# Cypress +/cypress/videos/ +/cypress/screenshots/ + +# Vitest +__screenshots__/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..fa345b3 --- /dev/null +++ b/.npmrc @@ -0,0 +1,5 @@ +# 设置包注册表镜像 +registry=https://registry.npmmirror.com/ + +# 设置 node-sass 二进制包的镜像(非常重要,能解决很多安装失败问题) +sass_binary_site=https://npmmirror.com/mirrors/node-sass/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..67a6a4e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,12 @@ +# 依赖目录 +node_modules/ +miniprogram_npm/ + +# 构建产物 +dist/ +coverage/ + +# 其他 +*.log +.DS_Store +package-lock.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..82b4a72 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "singleQuote": true, + "printWidth": 100, + "overrides": [ + { + "files": "*.wxml", + "options": { + "parser": "html" + } + }, + { + "files": "*.wxss", + "options": { + "parser": "css" + } + } + ] +} diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000..9a84235 --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,63 @@ +import eslint from '@eslint/js' +import tseslint from 'typescript-eslint' +import prettierConfig from 'eslint-config-prettier' +import prettierPlugin from 'eslint-plugin-prettier' + +export default tseslint.config( + // 全局忽略的文件和目录 + { + ignores: [ + '**/node_modules/**', + '**/miniprogram_npm/**', + '**/dist/**', + '**/coverage/**', + '**/*.js.map', + '**/typings/**', + '**/*.d.ts', + ], + }, + + // ESLint 推荐规则 + eslint.configs.recommended, + + // TypeScript ESLint 推荐规则 + ...tseslint.configs.recommended, + + // 项目特定配置 + { + files: ['**/*.ts'], + languageOptions: { + parser: tseslint.parser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: './tsconfig.json', + }, + }, + plugins: { + '@typescript-eslint': tseslint.plugin, + prettier: prettierPlugin, + }, + rules: { + // Prettier 集成 + 'prettier/prettier': 'error', + + // TypeScript 规则调整(根据小程序特点) + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + + // 通用规则 + 'no-console': ['warn', { allow: ['warn', 'error'] }], + 'no-debugger': 'warn', + }, + }, + + // Prettier 配置(禁用与 Prettier 冲突的规则) + prettierConfig, +) diff --git a/miniprogram/api/login.ts b/miniprogram/api/login.ts new file mode 100644 index 0000000..a5a4481 --- /dev/null +++ b/miniprogram/api/login.ts @@ -0,0 +1,31 @@ +import request from '../utils/request' +import { StandardResponse } from './types' + +/** + * 登录接口请求参数类型 + */ +export interface LoginParams { + userName: string + password: string +} + +/** + * 用户信息数据类型 + */ +export interface UserInfoData { + id: number + username: string + nickname: string + avatar: string + email: string + phone: string +} + +/** + * 登录接口 + * @param params 登录参数 + * @returns 返回标准响应格式的登录数据 + */ +export const loginReq = (params: LoginParams) => { + return request.post>('/wechatLogin/wechatLogin.action', params) +} diff --git a/miniprogram/api/types.ts b/miniprogram/api/types.ts new file mode 100644 index 0000000..e0a092d --- /dev/null +++ b/miniprogram/api/types.ts @@ -0,0 +1,8 @@ +/** + * 标准响应数据格式 + */ +export interface StandardResponse { + code: number + data: T + message: string +} diff --git a/miniprogram/app.json b/miniprogram/app.json new file mode 100644 index 0000000..57bc196 --- /dev/null +++ b/miniprogram/app.json @@ -0,0 +1,14 @@ +{ + "pages": ["pages/date/date", "pages/login/login", "pages/index/index"], + "window": { + "navigationStyle": "default", + "navigationBarTextStyle": "black", + "navigationBarBackgroundColor": "#ffffff", + "navigationBarTitleText": "My Weapp Template" + }, + "style": "v2", + "renderer": "webview", + "componentFramework": "glass-easel", + "sitemapLocation": "sitemap.json", + "lazyCodeLoading": "requiredComponents" +} diff --git a/miniprogram/app.scss b/miniprogram/app.scss new file mode 100644 index 0000000..3662180 --- /dev/null +++ b/miniprogram/app.scss @@ -0,0 +1,18 @@ +/**app.wxss**/ +page, +view, +scroll-view, +image, +text { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; +} diff --git a/miniprogram/app.ts b/miniprogram/app.ts new file mode 100644 index 0000000..25d3d1e --- /dev/null +++ b/miniprogram/app.ts @@ -0,0 +1,5 @@ +// app.ts +App({ + globalData: {}, + onLaunch() {}, +}) diff --git a/miniprogram/pages/date/date.json b/miniprogram/pages/date/date.json new file mode 100644 index 0000000..a97367d --- /dev/null +++ b/miniprogram/pages/date/date.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} diff --git a/miniprogram/pages/date/date.scss b/miniprogram/pages/date/date.scss new file mode 100644 index 0000000..e38e96b --- /dev/null +++ b/miniprogram/pages/date/date.scss @@ -0,0 +1,97 @@ +/* pages/date/date.wxss */ +.container { + padding: 20rpx; + background-color: #f5f5f5; + min-height: 100vh; +} + +.header { + margin-bottom: 30rpx; + text-align: center; +} + +.title { + font-size: 36rpx; + font-weight: bold; + color: #333; +} + +.section { + width: 100%; + background-color: #fff; + border-radius: 16rpx; + padding: 30rpx; + margin-bottom: 30rpx; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); +} + +.section-title { + font-size: 32rpx; + font-weight: bold; + color: #333; + margin-bottom: 10rpx; +} + +.section-desc { + font-size: 24rpx; + color: #666; + margin-bottom: 20rpx; + line-height: 1.6; +} + +.example-list { + display: flex; + flex-direction: column; + gap: 24rpx; +} + +.example-item { + padding: 20rpx; + background-color: #f9f9f9; + border-radius: 12rpx; + border-left: 4rpx solid #1890ff; +} + +.example-label { + font-size: 28rpx; + font-weight: 600; + color: #333; + margin-bottom: 8rpx; +} + +.example-format { + font-size: 24rpx; + color: #999; + margin-bottom: 12rpx; + font-family: 'Courier New', monospace; +} + +.example-value { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16rpx; +} + +.result-text { + flex: 1; + font-size: 26rpx; + color: #1890ff; + word-break: break-all; + font-family: 'Courier New', monospace; +} + +.copy-btn { + padding: 8rpx 20rpx; + background-color: #1890ff; + color: #fff; + font-size: 24rpx; + border-radius: 8rpx; + white-space: nowrap; + flex-shrink: 0; +} + +.copy-btn:active { + background-color: #40a9ff; + opacity: 0.8; +} diff --git a/miniprogram/pages/date/date.ts b/miniprogram/pages/date/date.ts new file mode 100644 index 0000000..5dff8b9 --- /dev/null +++ b/miniprogram/pages/date/date.ts @@ -0,0 +1,204 @@ +// pages/date/date.ts +import { formatTime, formatDateTime } from '../../utils/util' + +Page({ + /** + * 页面的初始数据 + */ + data: { + // formatTime 示例 + formatTimeExamples: [] as Array<{ label: string; value: string }>, + // formatDateTime 示例 - 不同格式模板 + formatDateTimeExamples: [] as Array<{ label: string; format: string; value: string }>, + // formatDateTime 示例 - 不同输入类型 + inputTypeExamples: [] as Array<{ label: string; input: string; value: string }>, + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad() { + this.initExamples() + }, + + /** + * 初始化所有示例数据 + */ + initExamples() { + const now = new Date() + const timestamp = now.getTime() + const dateString = '2024-01-15 14:30:45' + const chineseDateString = '2024年1月15日' + + // formatTime 示例 + const formatTimeExamples = [ + { + label: '当前时间', + value: formatTime(now), + }, + { + label: '指定日期', + value: formatTime(new Date(2024, 0, 15, 14, 30, 45)), + }, + { + label: '昨天', + value: formatTime(new Date(timestamp - 24 * 60 * 60 * 1000)), + }, + { + label: '明天', + value: formatTime(new Date(timestamp + 24 * 60 * 60 * 1000)), + }, + ] + + // formatDateTime 示例 - 不同格式模板 + const formatDateTimeExamples = [ + { + label: '默认格式(YYYY/MM/DD HH:mm:ss)', + format: 'YYYY/MM/DD HH:mm:ss', + value: formatDateTime(now), + }, + { + label: '中文日期格式', + format: 'YYYY年MM月DD日 HH:mm:ss', + value: formatDateTime(now, 'YYYY年MM月DD日 HH:mm:ss'), + }, + { + label: '短日期格式', + format: 'YY/MM/DD', + value: formatDateTime(now, 'YY/MM/DD'), + }, + { + label: '12小时制格式', + format: 'YYYY-MM-DD hh:mm:ss A', + value: formatDateTime(now, 'YYYY-MM-DD hh:mm:ss A'), + }, + { + label: '24小时制格式', + format: 'YYYY-MM-DD HH:mm:ss', + value: formatDateTime(now, 'YYYY-MM-DD HH:mm:ss'), + }, + { + label: '仅日期', + format: 'YYYY-MM-DD', + value: formatDateTime(now, 'YYYY-MM-DD'), + }, + { + label: '仅时间', + format: 'HH:mm:ss', + value: formatDateTime(now, 'HH:mm:ss'), + }, + { + label: '带毫秒', + format: 'YYYY-MM-DD HH:mm:ss.SSS', + value: formatDateTime(now, 'YYYY-MM-DD HH:mm:ss.SSS'), + }, + { + label: '美式日期格式', + format: 'MM/DD/YYYY', + value: formatDateTime(now, 'MM/DD/YYYY'), + }, + { + label: '完整中文格式', + format: 'YYYY年MM月DD日 HH时mm分ss秒', + value: formatDateTime(now, 'YYYY年MM月DD日 HH时mm分ss秒'), + }, + ] + + // formatDateTime 示例 - 不同输入类型 + const inputTypeExamples = [ + { + label: 'Date 对象', + input: 'new Date()', + value: formatDateTime(now), + }, + { + label: '时间戳(数字)', + input: `${timestamp}`, + value: formatDateTime(timestamp), + }, + { + label: '日期字符串(标准格式)', + input: dateString, + value: formatDateTime(dateString), + }, + { + label: '中文日期字符串', + input: chineseDateString, + value: formatDateTime(chineseDateString), + }, + { + label: '仅年份字符串', + input: '2024', + value: formatDateTime('2024'), + }, + { + label: '年月字符串', + input: '2024/01', + value: formatDateTime('2024/01'), + }, + ] + + this.setData({ + formatTimeExamples, + formatDateTimeExamples, + inputTypeExamples, + }) + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() {}, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() {}, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() {}, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() {}, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() {}, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() {}, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() {}, + + /** + * 复制文本到剪贴板 + */ + copyText(e: WechatMiniprogram.Touch) { + const { text } = e.currentTarget.dataset + if (!text) { + return + } + + wx.setClipboardData({ + data: text, + success: () => { + wx.showToast({ + title: '复制成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + }, + }) + }, +}) diff --git a/miniprogram/pages/date/date.wxml b/miniprogram/pages/date/date.wxml new file mode 100644 index 0000000..8d81ef5 --- /dev/null +++ b/miniprogram/pages/date/date.wxml @@ -0,0 +1,74 @@ + + + + 日期时间格式化示例 + + + + + formatTime 函数示例 + 固定格式:YYYY/MM/DD HH:mm:ss + + + {{item.label}}: + + {{item.value}} + + 复制 + + + + + + + + + formatDateTime 函数示例 - 不同格式模板 + 支持自定义格式模板,灵活配置日期时间显示格式 + + + {{item.label}} + 格式模板:{{item.format}} + + {{item.value}} + + 复制 + + + + + + + + + formatDateTime 函数示例 - 不同输入类型 + 支持 Date 对象、时间戳、日期字符串等多种输入类型 + + + {{item.label}} + 输入:{{item.input}} + + {{item.value}} + + 复制 + + + + + + \ No newline at end of file diff --git a/miniprogram/pages/index/index.json b/miniprogram/pages/index/index.json new file mode 100644 index 0000000..a97367d --- /dev/null +++ b/miniprogram/pages/index/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} diff --git a/miniprogram/pages/index/index.scss b/miniprogram/pages/index/index.scss new file mode 100644 index 0000000..19cc86f --- /dev/null +++ b/miniprogram/pages/index/index.scss @@ -0,0 +1,133 @@ +/* pages/index.wxss */ +.container { + padding: 40rpx; + background-color: #f5f5f5; + min-height: 100vh; +} + +.header { + text-align: center; + margin-bottom: 40rpx; +} + +.title { + font-size: 36rpx; + font-weight: bold; + color: #333; +} + +.section { + width: 100%; + background-color: #fff; + border-radius: 16rpx; + padding: 30rpx; + margin-bottom: 30rpx; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); +} + +.section-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + margin-bottom: 24rpx; + padding-bottom: 16rpx; + border-bottom: 2rpx solid #eee; +} + +.input-textarea { + width: 100%; + min-height: 200rpx; + padding: 20rpx; + border: 2rpx solid #e0e0e0; + border-radius: 8rpx; + font-size: 28rpx; + background-color: #fafafa; + box-sizing: border-box; +} + +.action-bar { + display: flex; + gap: 20rpx; + margin-bottom: 24rpx; +} + +.btn { + flex: 1; + border-radius: 8rpx; + font-size: 28rpx; + border: none; +} + +.btn-primary { + background-color: #07c160; + color: #fff; +} + +.btn-primary:active { + background-color: #06ad56; +} + +.btn-secondary { + background-color: #576b95; + color: #fff; +} + +.btn-secondary:active { + background-color: #4a5d84; +} + +.result-box { + margin-bottom: 24rpx; + padding: 20rpx; + background-color: #fafafa; + border-radius: 8rpx; + border: 2rpx solid #e0e0e0; +} + +.result-label { + font-size: 24rpx; + color: #666; + margin-bottom: 12rpx; +} + +.result-content { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16rpx; +} + +.result-text { + flex: 1; + font-size: 26rpx; + color: #333; + word-break: break-all; + line-height: 1.6; +} + +.copy-btn { + padding: 8rpx 20rpx; + background-color: #07c160; + color: #fff; + font-size: 24rpx; + border-radius: 6rpx; + white-space: nowrap; +} + +.copy-btn:active { + background-color: #06ad56; +} + +.error-box { + margin-top: 30rpx; + padding: 20rpx; + background-color: #fff3cd; + border: 2rpx solid #ffc107; + border-radius: 8rpx; +} + +.error-text { + font-size: 26rpx; + color: #856404; + line-height: 1.6; +} diff --git a/miniprogram/pages/index/index.ts b/miniprogram/pages/index/index.ts new file mode 100644 index 0000000..9c267e5 --- /dev/null +++ b/miniprogram/pages/index/index.ts @@ -0,0 +1,301 @@ +// pages/index.ts +import { Encrypt, Decrypt, BASE64Encrypt, BASE64Decrypt, AESError } from '../../utils/aes' + +Page({ + /** + * 页面的初始数据 + */ + data: { + // 输入原文 + plainText: 'Hello, 小程序 AES 加密示例!', + // 标准 Base64 加密结果 + encryptedText: '', + // 标准 Base64 解密结果 + decryptedText: '', + // URL Safe Base64 加密结果 + base64EncryptedText: '', + // URL Safe Base64 解密结果 + base64DecryptedText: '', + // 错误信息 + errorMessage: '', + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad() { + // 页面加载时自动执行一次加密解密示例 + this.handleEncrypt() + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() {}, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() {}, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() {}, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() {}, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() {}, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() {}, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() {}, + + /** + * 输入原文变化 + */ + onPlainTextInput(e: WechatMiniprogram.Input) { + this.setData({ + plainText: e.detail.value, + errorMessage: '', + }) + }, + + /** + * 执行标准 Base64 加密 + */ + handleEncrypt() { + try { + const { plainText } = this.data + if (!plainText.trim()) { + wx.showToast({ + title: '请输入要加密的内容', + icon: 'none', + }).catch(() => { + console.error('showToast error') + }) + return + } + + // 执行加密 + const encrypted = Encrypt(plainText) + this.setData({ + encryptedText: encrypted, + errorMessage: '', + }) + + wx.showToast({ + title: '加密成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + } catch (error) { + const errorMsg = error instanceof AESError ? error.message : '加密失败' + this.setData({ + errorMessage: errorMsg, + }) + wx.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + } + }, + + /** + * 执行标准 Base64 解密 + */ + handleDecrypt() { + try { + const { encryptedText } = this.data + if (!encryptedText.trim()) { + wx.showToast({ + title: '请输入要解密的内容', + icon: 'none', + }).catch(() => { + console.error('showToast error') + }) + return + } + + // 执行解密 + const decrypted = Decrypt(encryptedText) + if (decrypted === null) { + this.setData({ + errorMessage: '解密失败:密钥不匹配或密文被篡改', + }) + wx.showToast({ + title: '解密失败', + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + return + } + + this.setData({ + decryptedText: decrypted, + errorMessage: '', + }) + + wx.showToast({ + title: '解密成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + } catch (error) { + const errorMsg = error instanceof AESError ? error.message : '解密失败' + this.setData({ + errorMessage: errorMsg, + }) + wx.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + } + }, + + /** + * 执行 URL Safe Base64 加密 + */ + handleBase64Encrypt() { + try { + const { plainText } = this.data + if (!plainText.trim()) { + wx.showToast({ + title: '请输入要加密的内容', + icon: 'none', + }).catch(() => { + console.error('showToast error') + }) + return + } + + // 执行 URL Safe Base64 加密 + const encrypted = BASE64Encrypt(plainText) + this.setData({ + base64EncryptedText: encrypted, + errorMessage: '', + }) + + wx.showToast({ + title: '加密成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + } catch (error) { + const errorMsg = error instanceof AESError ? error.message : '加密失败' + this.setData({ + errorMessage: errorMsg, + }) + wx.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + } + }, + + /** + * 执行 URL Safe Base64 解密 + */ + handleBase64Decrypt() { + try { + const { base64EncryptedText } = this.data + if (!base64EncryptedText.trim()) { + wx.showToast({ + title: '请输入要解密的内容', + icon: 'none', + }).catch(() => { + console.error('showToast error') + }) + return + } + + // 执行 URL Safe Base64 解密 + const decrypted = BASE64Decrypt(base64EncryptedText) + if (decrypted === null) { + this.setData({ + errorMessage: '解密失败:密钥不匹配或密文被篡改', + }) + wx.showToast({ + title: '解密失败', + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + return + } + + this.setData({ + base64DecryptedText: decrypted, + errorMessage: '', + }) + + wx.showToast({ + title: '解密成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + } catch (error) { + const errorMsg = error instanceof AESError ? error.message : '解密失败' + this.setData({ + errorMessage: errorMsg, + }) + wx.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000, + }).catch(() => { + console.error('showToast error') + }) + } + }, + + /** + * 复制文本到剪贴板 + */ + copyText(e: WechatMiniprogram.Touch) { + const { text } = e.currentTarget.dataset + if (!text) { + return + } + + wx.setClipboardData({ + data: text, + success: () => { + wx.showToast({ + title: '复制成功', + icon: 'success', + }).catch(() => { + console.error('showToast error') + }) + }, + }) + }, +}) diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml new file mode 100644 index 0000000..32e2135 --- /dev/null +++ b/miniprogram/pages/index/index.wxml @@ -0,0 +1,104 @@ + + + + AES 加密解密示例 + + + + + 原文输入 +