commit 1eeb944be61cd8fff6422c899d4558c655f0e820 Author: npmrun <1549469775@qq.com> Date: Mon Jun 9 00:41:52 2025 +0800 添加应用基础结构和样式,包含首页、导航栏、状态栏等组件,更新数据管理功能,增加日期处理工具,完善项目配置文件 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..efe7735 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +unpackage \ No newline at end of file diff --git a/App.uvue b/App.uvue new file mode 100644 index 0000000..58ec612 --- /dev/null +++ b/App.uvue @@ -0,0 +1,46 @@ + + + \ No newline at end of file diff --git a/assets/fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf b/assets/fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf new file mode 100644 index 0000000..ba2ad8a Binary files /dev/null and b/assets/fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf differ diff --git a/assets/style/common.scss b/assets/style/common.scss new file mode 100644 index 0000000..17c6d3e --- /dev/null +++ b/assets/style/common.scss @@ -0,0 +1,6 @@ + +@font-face { + font-family: ZhanKuKuaiLeTi; + src: url('@/assets/fonts/ZhanKuKuaiLeTi2016XiuDingBan-1.ttf'); +} + \ No newline at end of file diff --git a/components/x-navbar/x-navbar.uvue b/components/x-navbar/x-navbar.uvue new file mode 100644 index 0000000..f4a83cc --- /dev/null +++ b/components/x-navbar/x-navbar.uvue @@ -0,0 +1,85 @@ + + + + + \ No newline at end of file diff --git a/components/x-page/x-page.uvue b/components/x-page/x-page.uvue new file mode 100644 index 0000000..d6cf89e --- /dev/null +++ b/components/x-page/x-page.uvue @@ -0,0 +1,35 @@ + + + + + \ No newline at end of file diff --git a/components/x-status-bar/x-status-bar.uvue b/components/x-status-bar/x-status-bar.uvue new file mode 100644 index 0000000..a1ad08b --- /dev/null +++ b/components/x-status-bar/x-status-bar.uvue @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/data/index.uts b/data/index.uts new file mode 100644 index 0000000..db36be0 --- /dev/null +++ b/data/index.uts @@ -0,0 +1,116 @@ +const primaryKey = "id"; +const allData: IItem[] = []; + +interface IItem { + id?: number; + timestamp: string; + [key: string]: any; // 允许任意其他字段 +} +interface IPartialItem { + id?: number; + timestamp?: string; + [key: string]: any; // 允许任意其他字段 +} + +let key = 0; + +// 添加记录 +function addRecord(data: IItem): IItem { + const id = data.id ?? ++key; + const existingIndex = allData.findIndex((v) => v.id === id); + + if (existingIndex === -1) { + const newRecord = { + id, + ...data, + timestamp: data.timestamp || String(Date.now()) + }; + allData.push(newRecord); + return newRecord; + } else { + throw new Error(`Record with id ${id} already exists`); + } +} + +// 查询所有记录*- +function getAllRecords(): IItem[] { + return [...allData]; // 返回副本以避免外部修改 +} + +// 根据ID查询单条记录 +function getRecordById(id: number): IItem | undefined { + return allData.find((v) => v.id === id); +} + +// 更新记录 +function updateRecord(id: number, updates: IPartialItem): IItem | undefined { + const index = allData.findIndex((v) => v.id === id); + if (index !== -1) { + const updatedRecord = { + ...allData[index], + ...updates, + id // 确保ID不会被更新 + }; + allData[index] = updatedRecord; + return updatedRecord; + } + return undefined; +} + +// 删除记录 +function deleteRecord(id: number): boolean { + const index = allData.findIndex((v) => v.id === id); + if (index !== -1) { + allData.splice(index, 1); + return true; + } + return false; +} + +// 查询记录 (简单条件) +function queryRecords(conditions: IPartialItem): IItem[] { + return allData.filter(item => { + return Object.entries(conditions).every(([key, value]: any) => { + return item[key] === value; + }); + }); +} + +// 事务支持 +function transaction(operations: (() => void)[]): boolean { + const originalData = [...allData]; + try { + operations.forEach(op => op()); + return true; + } catch (error) { + // 回滚 + allData.length = 0; + allData.push(...originalData); + console.error('Transaction failed:', error); + return false; + } +} + +// 示例使用 +try { + // 添加记录 + addRecord({ timestamp: String(Date.now()), name: 'Item 1', price: 100 }); + addRecord({ timestamp: String(Date.now()), name: 'Item 2', price: 200 }); + + // 更新记录 + transaction([ + () => updateRecord(1, { price: 150 }), + () => addRecord({ timestamp: String(Date.now()), name: 'Item 3' }) + ]); + + // 查询 + const expensiveItems = queryRecords({ price: 200 }); + console.log(expensiveItems); + + // 删除 + deleteRecord(2); + + console.log(getAllRecords()); +} catch (error) { + console.error('Database operation failed:', error); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..8ac465c --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/main.uts b/main.uts new file mode 100644 index 0000000..3b8febc --- /dev/null +++ b/main.uts @@ -0,0 +1,10 @@ +import App from './App.uvue' +import "@/assets/style/common.scss" + +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..cd37515 --- /dev/null +++ b/manifest.json @@ -0,0 +1,48 @@ +{ + "name": "uni-x", + "appid": "__UNI__D9CF915", + "description": "", + "versionName": "1.0.0", + "versionCode": "100", + "uni-app-x": {}, + /* 快应用特有相关 */ + "quickapp": {}, + /* 小程序特有相关 */ + "mp-weixin": { + "appid": "", + "setting": { + "urlCheck": false + }, + "usingComponents": true + }, + "mp-alipay": { + "usingComponents": true + }, + "mp-baidu": { + "usingComponents": true + }, + "mp-toutiao": { + "usingComponents": true + }, + "uniStatistics": { + "enable": false + }, + "vueVersion": "3", + "app": { + "distribute": { + "icons": { + "android": { + "hdpi": "", + "xhdpi": "", + "xxhdpi": "", + "xxxhdpi": "" + } + } + } + }, + "web": { + "router": { + "mode": "" + } + } +} \ No newline at end of file diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..55caef0 --- /dev/null +++ b/pages.json @@ -0,0 +1,17 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationStyle": "custom" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app x", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "uniIdRouter": {} +} diff --git a/pages/index/index.uvue b/pages/index/index.uvue new file mode 100644 index 0000000..1e82fae --- /dev/null +++ b/pages/index/index.uvue @@ -0,0 +1,222 @@ + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..7585ebf --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +[](https://ext.dcloud.net.cn/plugin?id=16902) \ No newline at end of file diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..b9249e9 --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/utils/date.uts b/utils/date.uts new file mode 100644 index 0000000..2e482a6 --- /dev/null +++ b/utils/date.uts @@ -0,0 +1,103 @@ + +export function getWeek(time : Date) { + let week = time.getDay() // 当前周几 + // week = (week - 1) < 0 ? 0 : (week - 1) + if(week == 0) week = 7 // 0 表示周日 + return week +} + +export function getCurrentMonth(time : Date) : number { + let month = time.getMonth() + 1 + return month +} + +export function getLastMonth(curDate : Date) { + let lastDate = new Date() + lastDate.setMonth(curDate.getMonth() - 1) + return lastDate +} + +export function getLastMonthDay(curDate : Date, offset : number) { + let lastDate = new Date(curDate.getTime()) + lastDate.setHours(-24 * offset); + return lastDate +} + +export function getNextMonthDay(curDate : Date, offset : number) { + let lastDate = new Date(curDate.getTime()) + lastDate.setHours(24 * offset); + return lastDate +} + + +export function format(time : Date) { + return `${time.getFullYear()}-${time.getMonth() + 1}-${time.getDate()}` +} + +export function formatFull(time : Date) { + const year = (time.getFullYear()) + "" + const month = (time.getMonth() + 1) + "" + const date = (time.getDate()) + "" + const hour = (time.getHours()) + "" + const minute = (time.getMinutes()) + "" + const second = (time.getSeconds()) + "" + return `${year}-${month.padStart(2, '0')}-${date.padStart(2, '0')} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}:${second.padStart(2, '0')}` +} + +// 获取当前月份应该有多少天 +export function getCurMonthDayNum(time : Date) : number { + let day = 31; + let month = time.getMonth() + 1 + let year = time.getFullYear() + if ([1, 3, 5, 7, 8, 10, 12].indexOf(month) != -1) { + day = 31; + } else if ([4, 6, 9, 11].indexOf(month) != -1) { + day = 30; + } else if (year % 4 == 0) { + day = 29 + } else { + day = 28 + } + return day +} + +export function generateDate(_nowDate : Date | string | number, format : (date : Date) => T = (v : Date) => (v as T)) { + if (typeof _nowDate === "string" || typeof _nowDate === "number") { + _nowDate = new Date(_nowDate as string) + } + + const allDate : T[] = [] + + let firstDate = new Date(_nowDate.getTime()) + firstDate.setDate(1) + const firstWeek = getWeek(firstDate) + console.log(firstDate.getTime()); + for (var i = 1; i < firstWeek; i++) { + const date = getLastMonthDay(firstDate, i) + allDate.unshift(format(new Date(date.getTime())) as T) + } + + let curDate = new Date(_nowDate.getTime()) + const allDay = getCurMonthDayNum(curDate) + for (var i = 1; i <= getCurMonthDayNum(curDate); i++) { + curDate.setDate(i) + allDate.push(format(new Date(curDate.getTime())) as T) + } + + let endDate = new Date(_nowDate.getTime()) + endDate.setDate(allDay) + const endWeek = 7 - getWeek(endDate) + for (var i = 1; i <= endWeek; i++) { + const date = getNextMonthDay(endDate, i) + allDate.push(format(new Date(date.getTime())) as T) + } + // 至少6行 + if (~~(allDate.length / 7) < 6) { + for (var i = endWeek + 1; i < endWeek + 1 + 7; i++) { + const date = getNextMonthDay(endDate, i) + allDate.push(format(new Date(date.getTime())) as T) + } + } + + return allDate +} \ No newline at end of file