diff --git a/package.json b/package.json
index 08a7388..da7bac7 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"@dcloudio/uni-quickapp-webview": "3.0.0-5020420260813003",
"@wot-ui/ui": "^2.3.2",
"miniprogram-api-typings": "^5.2.3",
+ "pinia": "^4.0.3",
"vue": "^3.4.21",
"vue-i18n": "^9.1.9"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c1d2813..6043782 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -62,6 +62,9 @@ importers:
miniprogram-api-typings:
specifier: ^5.2.3
version: 5.2.3
+ pinia:
+ specifier: ^4.0.3
+ version: 4.0.3(@vue/devtools-api@6.6.4)(typescript@4.9.5)(vue@3.5.42(typescript@4.9.5))
vue:
specifier: ^3.4.21
version: 3.5.42(typescript@4.9.5)
@@ -3578,6 +3581,16 @@ packages:
resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
engines: {node: '>=12'}
+ pinia@4.0.3:
+ resolution: {integrity: sha512-XMQqpvjgG7LMqVhhFUzKLT4KEbsYbfZZ0CZU9PgdFm1O2VKBmIkykL8+SfNhOaT7sR0wT6BEgKT0YNDYWgmVRA==}
+ peerDependencies:
+ '@vue/devtools-api': ^8.1.5
+ typescript: '>=5.6.0'
+ vue: ^3.5.11
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'}
@@ -9039,6 +9052,14 @@ snapshots:
picomatch@4.0.7: {}
+ pinia@4.0.3(@vue/devtools-api@6.6.4)(typescript@4.9.5)(vue@3.5.42(typescript@4.9.5)):
+ dependencies:
+ '@vue/devtools-api': 6.6.4
+ nostics: 1.2.0
+ vue: 3.5.42(typescript@4.9.5)
+ optionalDependencies:
+ typescript: 4.9.5
+
pirates@4.0.7: {}
pixelmatch@4.0.2:
diff --git a/project.config.json b/project.config.json
new file mode 100644
index 0000000..da2a8b8
--- /dev/null
+++ b/project.config.json
@@ -0,0 +1,24 @@
+{
+ "setting": {
+ "es6": true,
+ "postcss": true,
+ "minified": true,
+ "uglifyFileName": false,
+ "enhance": true,
+ "packNpmRelationList": [],
+ "babelSetting": {
+ "ignore": [],
+ "disablePlugins": [],
+ "outputPath": ""
+ },
+ "useCompilerPlugins": false
+ },
+ "compileType": "miniprogram",
+ "simulatorPluginLibVersion": {},
+ "packOptions": {
+ "ignore": [],
+ "include": []
+ },
+ "appid": "wxf7a95cb4373170c1",
+ "editorSetting": {}
+}
\ No newline at end of file
diff --git a/project.private.config.json b/project.private.config.json
new file mode 100644
index 0000000..044e3e8
--- /dev/null
+++ b/project.private.config.json
@@ -0,0 +1,14 @@
+{
+ "libVersion": "3.17.2",
+ "projectname": "patch-mp",
+ "setting": {
+ "urlCheck": true,
+ "coverView": true,
+ "lazyloadPlaceholderEnable": false,
+ "skylineRenderEnable": false,
+ "preloadBackgroundData": false,
+ "autoAudits": false,
+ "showShadowRootInWxmlPanel": true,
+ "compileHotReLoad": true
+ }
+}
\ No newline at end of file
diff --git a/src/components/CropPopup.vue b/src/components/CropPopup.vue
new file mode 100644
index 0000000..289242d
--- /dev/null
+++ b/src/components/CropPopup.vue
@@ -0,0 +1,124 @@
+
+
+
+ {{ patchStore.cropApiType === 'ADD' ? '新增作物' : '编辑作物' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+
+ 删除
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/components/PatchPopup.vue b/src/components/PatchPopup.vue
new file mode 100644
index 0000000..0f52975
--- /dev/null
+++ b/src/components/PatchPopup.vue
@@ -0,0 +1,106 @@
+
+
+
+ {{ patchStore.patchApiType === 'ADD' ? '新增菜地' : '编辑菜地' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+
+ 删除
+
+
+ 保存
+
+
+
+
+
+
diff --git a/src/components/RecordPopup.vue b/src/components/RecordPopup.vue
new file mode 100644
index 0000000..cb9a109
--- /dev/null
+++ b/src/components/RecordPopup.vue
@@ -0,0 +1,256 @@
+
+
+
+
+ {{ patchStore.recordApiType === 'ADD' ? '新增记录' : '编辑记录' }}
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+
+ 删除
+
+
+ 保存
+
+
+
+
+
+
+
+
+
diff --git a/src/main.ts b/src/main.ts
index 8e387cd..f2e44e1 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,9 +1,13 @@
import 'uno.css'
import { createSSRApp } from 'vue'
+import { createPinia } from 'pinia'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
+ const pinia = createPinia()
- return { app }
+ app.use(pinia)
+
+ return { app, pinia }
}
diff --git a/src/manifest.json b/src/manifest.json
index 309b9ec..27112cd 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,6 +1,6 @@
{
"name" : "",
- "appid" : "",
+ "appid" : "wxf7a95cb4373170c1",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
@@ -65,7 +65,7 @@
"mp-toutiao" : {
"usingComponents" : true
},
- "uniStatistics": {
+ "uniStatistics": {
"enable": false
},
"vueVersion" : "3"
diff --git a/src/pages.json b/src/pages.json
index 28df6e7..f1e170f 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -4,6 +4,10 @@
"path": "pages/index/index",
"style": { "navigationBarTitleText": "首页" }
},
+ {
+ "path": "pages/record/index",
+ "style": { "navigationBarTitleText": "记录" }
+ },
{
"path": "pages/user/index",
"style": { "navigationBarTitleText": "我的" }
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index 8ca34f1..8087a0e 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -13,52 +13,51 @@
-
-
+
+
+
+ {{ item.name }}
+ {{ item.location }}
+
+
+
+
+
+ 暂无记录
+
+
-
+
- 西红柿
- 粉果番茄
+ {{ item.crop.name }}
+ {{ item.crop.variety }}
-
-
+
+
+
+
+
-
-
+
+
-
-
+
-
-
-
-
- 黄瓜
- 旱黄瓜
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -67,9 +66,13 @@
import { computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import appLogo from '@/static/logo.png'
+import { usePatchStore } from "@/stores/patch";
+import type {ICrop, IPatch} from "@/types";
+import PatchPopup from "@/components/PatchPopup.vue";
defineOptions({ name: 'Home' })
+const patchStore = usePatchStore()
const imgURL = appLogo
// ===== 时间 =====
@@ -90,10 +93,48 @@ const today = computed(() => {
return `${m}月${d}日 周${w}`
})
+onShow(async () => {
+ await loadData()
+})
-onShow(() => loadData())
+async function loadData() {
+ await patchStore.queryPatchList()
+}
-function loadData() {
+function addPatchClick() {
+ patchStore.patchForm = {
+ id: 0,
+ name: '',
+ location: '',
+ status: ''
+ }
+ patchStore.patchApiType = 'ADD'
+ patchStore.showPatchPopup = true
+ patchStore.showPatchFab = false
+}
+function editPatchClick(patch: IPatch) {
+ patchStore.patchForm = JSON.parse(JSON.stringify(patch))
+ patchStore.patchApiType = 'UPDATE'
+ patchStore.showPatchPopup = true
+ patchStore.showPatchFab = false
+}
+
+async function viewDetailClick(patch: IPatch) {
+ patchStore.currentPatch = patch
+
+ if (patch.crop) {
+ await patchStore.queryRecordList(patch.crop.id)
+ } else {
+ patchStore.recordList = []
+ }
+ wx.navigateTo({
+ url: '/pages/record/index'
+ })
+}
+
+function handlePreview(crop: ICrop) {
+ const fullUrls = crop.images?.map(url => `${patchStore.baseUrl}/${url}`) as string[]
+ uni.previewImage({ urls: fullUrls, current: fullUrls[0] })
}
diff --git a/src/pages/record/index.vue b/src/pages/record/index.vue
new file mode 100644
index 0000000..22ee0d6
--- /dev/null
+++ b/src/pages/record/index.vue
@@ -0,0 +1 @@
+
{{ patchStore.currentPatch.crop.name }}
{{ patchStore.currentPatch.crop.variety }}
点击添加作物
{{ item.type }}
{{ item.stage }}
{{ item.date }}
{{ item.content }}
\ No newline at end of file
diff --git a/src/pages/user/index.vue b/src/pages/user/index.vue
index cb7c469..71e8d26 100644
--- a/src/pages/user/index.vue
+++ b/src/pages/user/index.vue
@@ -1,105 +1,8 @@
-
-
-
-
-
-
- 西红柿
-
-
-
-
-
-
-
-
- 💧 浇水
- 🌱 开花期
- 06-20 08:30
-
-
-
-
- 浇透水,土壤湿度约70%
-
-
-
-
-
-
-
- 🌿 施肥
- 🌱 开花期
- 06-18 17:00
-
-
-
-
-
- 追施磷酸二氢钾,800倍叶面喷施
-
-
-
-
-
-
-
- 🐛 病虫害防治
- ⚠️ 发现蚜虫
- 06-15 09:00
-
-
-
-
- 叶片背面发现少量蚜虫,喷施吡虫啉1000倍液
-
-
-
-
-
-
-
- ✂️ 整枝打杈
- 🌱 开花期
- 06-12 16:30
-
-
-
-
- 摘除第一穗花以下所有侧枝,保留主蔓
-
-
-
-
-
-
-
-
- 🌱 播种
- 📅 苗期
- 04-10 10:00
-
-
-
-
- 穴盘育苗,覆土1cm,浇透水,放置于温暖通风处
-
-
-
-
+
+
diff --git a/src/stores/patch.ts b/src/stores/patch.ts
new file mode 100644
index 0000000..e3623ce
--- /dev/null
+++ b/src/stores/patch.ts
@@ -0,0 +1,259 @@
+import { defineStore } from 'pinia'
+import type { ICrop, IPatch, IRecord } from "@/types";
+import type { UploadFile } from "@wot-ui/ui/components/wd-upload/types";
+
+export const usePatchStore = defineStore('patch', {
+ state: () => ({
+ baseUrl: 'https://cxx0822.s.3q.hair',
+ showPatchFab: true,
+ patchList: [] as IPatch[],
+ patchApiType: 'ADD' as 'ADD' | 'UPDATE' | 'DELETE',
+ patchForm: {
+
+ } as IPatch,
+ showPatchPopup: false,
+ currentPatch: {} as IPatch,
+ recordList: [] as IRecord[],
+ cropApiType: 'ADD' as 'ADD' | 'UPDATE' | 'DELETE',
+ cropForm: {
+
+ } as ICrop,
+ showCropPopup: false,
+ showRecordFab: true,
+ showRecordPopup: false,
+ recordApiType: 'ADD' as 'ADD' | 'UPDATE' | 'DELETE',
+ recordForm: {
+ id: 0,
+ crop_id: 0,
+ type: '',
+ date: '',
+ content: '',
+ images: [],
+ videos: [],
+ stage: '',
+ } as IRecord,
+ imageFileList: [] as UploadFile[],
+ videoFileList: [] as UploadFile[],
+ }),
+ actions: {
+ async queryPatchList() {
+ this.patchList = await this.queryPatchListApi()
+ },
+ async queryPatch(patchId: number) {
+ this.currentPatch = await this.queryPatchApi(patchId)
+ },
+ async queryRecordList(cropId: number) {
+ this.recordList = await this.queryRecordListApi(cropId)
+ },
+ async queryPatchListApi() {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/patches`,
+ method: 'GET',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(res.data as IPatch[])
+ } else {
+ reject({ status: res.statusCode, data: res.data })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async queryPatchApi(patchId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/patches/${patchId}`,
+ method: 'GET',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(res.data as IPatch)
+ } else {
+ reject({ status: res.statusCode, data: res.data })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async addPatchApi() {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/patches`,
+ method: 'POST',
+ header: { 'Content-Type': 'application/json' },
+ data: this.patchForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async updatePatchApi(patchId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/patches/${patchId}`,
+ method: 'PUT',
+ header: { 'Content-Type': 'application/json' },
+ data: this.patchForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async deletePatchApi(patchId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/patches/${patchId}`,
+ method: 'DELETE',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async addCropApi() {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/crops`,
+ method: 'POST',
+ header: { 'Content-Type': 'application/json' },
+ data: this.cropForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async updateCropApi(cropId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/crops/${cropId}`,
+ method: 'PUT',
+ header: { 'Content-Type': 'application/json' },
+ data: this.cropForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async deleteCropApi(cropId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/crops/${cropId}`,
+ method: 'DELETE',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async queryRecordListApi(cropId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/records/crop/${cropId}`,
+ method: 'GET',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(res.data as IRecord[])
+ } else {
+ reject({ status: res.statusCode, data: res.data })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async addRecordApi() {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/records`,
+ method: 'POST',
+ header: { 'Content-Type': 'application/json' },
+ data: this.recordForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async updateRecordApi(recordId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/records/${recordId}`,
+ method: 'PUT',
+ header: { 'Content-Type': 'application/json' },
+ data: this.recordForm,
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ async deleteRecordApi(recordId: number) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.baseUrl}/patch-api/records/${recordId}`,
+ method: 'DELETE',
+ header: { 'Content-Type': 'application/json' },
+ success: (res) => {
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve(true)
+ } else {
+ reject({ status: res.statusCode, data: false })
+ }
+ },
+ fail: (err) => reject(err),
+ })
+ })
+ },
+ },
+})
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..8ddf0a1
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,27 @@
+export interface ICrop {
+ id: number
+ patch_id: number
+ name: string
+ variety: string
+ date: string
+ images?: string[]
+}
+
+export interface IPatch {
+ id: number
+ name: string
+ location: string
+ status: string
+ crop?: ICrop
+}
+
+export interface IRecord {
+ id: number
+ crop_id: number
+ type: string
+ date: string
+ content: string
+ images: string[]
+ videos: string[]
+ stage: string
+}
diff --git a/src/uni_modules/liu-drag-button_1.0.5/changelog.md b/src/uni_modules/liu-drag-button_1.0.5/changelog.md
new file mode 100644
index 0000000..f04925b
--- /dev/null
+++ b/src/uni_modules/liu-drag-button_1.0.5/changelog.md
@@ -0,0 +1,12 @@
+## 1.0.5(2023-07-13)
+优化
+## 1.0.4(2023-06-08)
+增加预览二维码
+## 1.0.3(2023-05-31)
+增加license
+## 1.0.2(2023-04-28)
+优化
+## 1.0.1(2023-04-26)
+增加示例
+## 1.0.0(2023-04-26)
+初始化发布
diff --git a/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue b/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue
new file mode 100644
index 0000000..8b10e7c
--- /dev/null
+++ b/src/uni_modules/liu-drag-button_1.0.5/components/liu-drag-button/liu-drag-button.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/uni_modules/liu-drag-button_1.0.5/license.md b/src/uni_modules/liu-drag-button_1.0.5/license.md
new file mode 100644
index 0000000..029bf39
--- /dev/null
+++ b/src/uni_modules/liu-drag-button_1.0.5/license.md
@@ -0,0 +1,6 @@
+### 1、本插件可免费下载使用;
+### 2、未经许可,严禁复制本插件派生同类插件上传插件市场;
+### 3、未经许可,严禁在插件市场恶意复制抄袭本插件进行违规获利;
+### 4、对本软件的任何使用都必须遵守这些条款,违反这些条款的个人或组织将面临法律追究。
+
+
diff --git a/src/uni_modules/liu-drag-button_1.0.5/package.json b/src/uni_modules/liu-drag-button_1.0.5/package.json
new file mode 100644
index 0000000..61a3c70
--- /dev/null
+++ b/src/uni_modules/liu-drag-button_1.0.5/package.json
@@ -0,0 +1,85 @@
+{
+ "id": "liu-drag-button",
+ "displayName": "可拖动悬浮按钮",
+ "version": "1.0.5",
+ "description": "可拖动的悬浮按钮,兼容小程序、H5,支持自动停靠,支持自定义样式,使用相当简单,源码简单易修改。",
+ "keywords": [
+ "悬浮按钮",
+ "拖拽按钮",
+ "拖动",
+ "按钮",
+ "拖拽"
+ ],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+ "dcloudext": {
+ "type": "component-vue",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "y",
+ "vue3": "u"
+ },
+ "App": {
+ "app-vue": "u",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/src/uni_modules/liu-drag-button_1.0.5/readme.md b/src/uni_modules/liu-drag-button_1.0.5/readme.md
new file mode 100644
index 0000000..848af4d
--- /dev/null
+++ b/src/uni_modules/liu-drag-button_1.0.5/readme.md
@@ -0,0 +1,36 @@
+# liu-drag-button适用于uni-app项目的可拖动悬浮按钮组件
+### 本组件目前兼容微信小程序、H5
+### 本组件是可拖动的悬浮按钮,兼容小程序、H5,支持自动停靠,支持自定义样式,源码简单易修改
+# --- 扫码预览、关注我们 ---
+
+## 扫码关注公众号,查看更多插件信息,预览插件效果!
+
+
+
+### 使用方式
+``` html
+按钮
+```
+``` javascript
+export default {
+ data() {
+ return {
+
+ };
+ },
+ methods: {
+ //点击按钮
+ clickBtn(){
+ console.log('按钮被点击了')
+ },
+ }
+}
+```
+
+### 属性说明
+| 名称 | 类型 | 默认值 | 描述 |
+| ----------------------------|--------------- | ------------------ | ---------------|
+| disabled | Boolean | false | 是否禁用拖动
+| canDocking | Boolean | true | 是否自动停靠
+| bottomPx | Number | 30 | 按钮默认位置离底部距离(px)
+| rightPx | Number | 0 | 按钮默认位置离右边距离(px)
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..224ab83
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,19 @@
+export function formatDate(ts: string | number) {
+ if (!ts)
+ return ''
+ const d = new Date(ts)
+ const pad = (n: number) => String(n).padStart(2, '0')
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
+}
+
+export function formatDateTime(ts: string | number) {
+ if (!ts)
+ return ''
+ const d = new Date(ts)
+ const pad = (n: number) => String(n).padStart(2, '0')
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
+}
+
+export function generateUniqueId() {
+ return Date.now() + '-' + Math.random().toString(36).slice(2, 6);
+}