feat: 页面提交

This commit is contained in:
huxuejian 2026-01-20 19:04:24 +08:00
parent daf049cb5a
commit 6ace7bd8fb
26 changed files with 1045 additions and 1132 deletions

16
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,16 @@
{ // launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}

View File

@ -0,0 +1,58 @@
<template>
<common-cell :name="name" :required="required">
<view class="form-content__wrapper" @click="select()">
<view class="flex-main-content truncate" :class="str ? '' : 'form__placeholder'">
{{ str || placeholder }}
</view>
<uni-icons class="form-arrow" type="arrowright"></uni-icons>
</view>
</common-cell>
</template>
<script setup>
import { computed } from 'vue';
import { set } from '@/utils/cache';
import commonCell from '../common-cell.vue';
const emits = defineEmits(['change']);
const props = defineProps({
form: {
type: Object,
default: () => ({})
},
name: {
default: ''
},
required: {
type: Boolean,
default: false
},
title: {
default: ''
},
})
const placeholder = computed(() => `请输入${props.name || ''}`)
const value = computed(() => props.form && props.form && Array.isArray(props.form[props.title]) ? props.form[props.title] : []);
const str = computed(() => value.value.join(','))
function change(e) {
emits('change', {
title: props.title,
value: e
})
}
function select() {
const eventName = `onChangeMultDisease_${+new Date()}`
uni.$once(eventName, change);
set('diagnosis-list-selections', value.value)
uni.navigateTo({
url: `/pages/library/diagnosis-list?eventName=${eventName}`
})
}
</script>
<style>
@import '../cell-style.css';
</style>

View File

@ -0,0 +1,110 @@
<template>
<view class="textarea-row">
<view class="form-row__label">
{{ name }}<text v-if="required" class="form-cell--required"></text>
</view>
<view class="flex flex-wrap">
<view v-for="(file, idx) in files" :key="idx" class="upload-item mt-10">
<image v-if="file.isImage" :src="file.url" class="w-full h-full"></image>
<image v-else src="/static/file.svg" class="w-full h-full"></image>
<uni-icons type="close" :size="32" color="red" class="remove-icon" @click="remove(idx)"></uni-icons>
</view>
<view v-if="value.length < 3"
class="upload-item border-primary mt-10 flex items-center justify-center text-primary" @click="addImage()">
<uni-icons type="camera" :size="40" color="#0074ff"></uni-icons>
</view>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue';
import { upload } from '@/utils/http';
import { loading, hideLoading, toast } from '@/utils/widget';
const emits = defineEmits(['change']);
const props = defineProps({
form: {
type: Object,
default: () => ({})
},
name: {
default: ''
},
required: {
type: Boolean,
default: false
},
title: {
default: ''
},
disableChange: {
type: Boolean,
default: false
}
})
const value = computed(() => Array.isArray(props.form[props.title]) ? props.form[props.title] : [])
const files = computed(() => value.value.map(i => {
return {
url: i.url,
name: i.name,
type: i.type,
isImage: /image/i.test(i.type)
}
}))
function addImage() {
uni.chooseImage({
count: 1,
success: async (res) => {
loading();
const result = await upload(res.tempFilePaths[0]);
hideLoading();
if (result) {
change([...value.value, { url: result, type: 'image/png' }])
} else {
toast('上传失败')
}
}
})
}
function change(value) {
emits('change', {
title: props.title,
value: value
})
}
function remove(idx) {
const value = [...files.value];
value.splice(idx, 1);
change(value)
}
</script>
<style lang="scss" scoped>
.upload-item {
position: relative;
width: 160rpx;
height: 160rpx;
border-radius: 16rpx;
box-sizing: border-box;
margin-right: 30rpx;
margin-bottom: 10rpx;
}
.textarea-row {
padding: 24rpx 30rpx;
border-bottom: 1px solid #eee;
font-size: 28rpx;
}
.remove-icon {
position: absolute;
top: -30rpx;
right: -30rpx;
z-index: 2;
}
</style>

View File

@ -1,11 +1,21 @@
<template>
<form-datepicker v-if="attrs.type === 'date'" v-bind="attrs" :form="form" :disableChange="disableChange" @change="change" />
<form-input v-else-if="attrs.type === 'input'" v-bind="attrs" :form="form" :disableChange="disableChange" @change="change" />
<form-radio v-else-if="attrs.type === 'radio'" v-bind="attrs" :form="form" :disableChange="disableChange" @change="change" />
<form-region v-else-if="attrs.type === 'region'" v-bind="attrs" :form="form" :disableChange="disableChange" @change="change" />
<form-select v-else-if="attrs.type === 'select'" v-bind="attrs" :form="form" :disableChange="disableChange" @change="change" />
<form-datepicker v-if="attrs.type === 'date'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-input v-else-if="attrs.type === 'input'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-radio v-else-if="attrs.type === 'radio'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-region v-else-if="attrs.type === 'region'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-select v-else-if="attrs.type === 'select'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-textarea v-else-if="attrs.type === 'textarea'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-mult-disease v-else-if="attrs.type === 'selfMultipleDiseases'" v-bind="attrs" :form="form"
@change="change"></form-mult-disease>
<form-mult-disease v-else-if="attrs.type === 'diagnosis'" v-bind="attrs" :form="form"
@change="change"></form-mult-disease>
<form-upload v-else-if="attrs.type === 'files'" v-bind="attrs" :form="form" @change="change" />
<!--
<form-operation v-else-if="attrs.title === 'surgicalHistory'" v-bind="attrs" :form="form" @change="change"
@ -25,6 +35,8 @@ import formRadio from './form-radio.vue';
import formDatepicker from './form-datepicker.vue';
import formRegion from './form-region.vue';
import formTextarea from './form-textarea.vue';
import formMultDisease from './form-multiple-diseases.vue';
import formUpload from './form-upload.vue';
defineProps({
form: {

View File

@ -1,9 +1,7 @@
<template>
<template v-for="item in formItems" :key="item.title">
<form-cell v-if="item.cellType === 'formCellItem'" v-bind="item" :form="form" :disableChange="disabledMap[item.title]"
@change="change" @addRule="addRule" />
<custom-cell v-else-if="item.cellType === 'customCellItem'" v-bind="item" :form="form"
:readonly="disabledMap[item.title]" @change="change" @addRule="addRule" />
<form-cell v-if="item.cellType === 'formCellItem'" v-bind="item" :form="form"
:disableChange="disabledMap[item.title]" @change="change" @addRule="addRule" />
</template>
<form-cell />
</template>
@ -34,9 +32,9 @@ const props = defineProps({
}
})
const formCellType = ['input', 'select', 'date', 'radio', 'region', 'textarea', 'multiSelectAndOther', 'selfMultipleDiseases'];
const formCellType = ['input', 'select', 'date', 'radio', 'region', 'textarea', 'multiSelectAndOther', 'selfMultipleDiseases', 'files','diagnosis'];
const formCellTitle = ['surgicalHistory'];
const customCellType = ['BMI', 'selfMultipleDiseases', 'bloodPressure', 'diagnosis'];
const customCellType = ['BMI', 'bloodPressure'];
const disabledMap = computed(() => props.disableTitles.reduce((m, i) => {
if (typeof i === 'string' && i.trim()) {
m[i] = true;

971
package-lock.json generated
View File

@ -1,953 +1,22 @@
{
"name": "ykt-wxapp",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ykt-wxapp",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"dayjs": "^1.11.10"
},
"devDependencies": {
"tailwindcss": "^3.4.3"
}
},
"node_modules/@alloc/quick-lru": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.walk": {
"version": "1.2.8",
"resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"dev": true
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true,
"bin": {
"cssesc": "bin/cssesc"
},
"engines": {
"node": ">=4"
}
},
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
},
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true,
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-core-module": {
"version": "2.16.1",
"resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
"dependencies": {
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"bin": {
"jiti": "bin/jiti.js"
}
},
"node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"dev": true,
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pirates": {
"version": "4.0.7",
"resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz",
"integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmmirror.com/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"dev": true,
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
"resolve": "^1.1.7"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"postcss": "^8.0.0"
}
},
"node_modules/postcss-js": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/postcss-js/-/postcss-js-4.1.0.tgz",
"integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"camelcase-css": "^2.0.1"
},
"engines": {
"node": "^12 || ^14 || >= 16"
},
"peerDependencies": {
"postcss": "^8.4.21"
}
},
"node_modules/postcss-load-config": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"lilconfig": "^3.1.1"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"jiti": ">=1.21.0",
"postcss": ">=8.0.9",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
},
"peerDependenciesMeta": {
"jiti": {
"optional": true
},
"postcss": {
"optional": true
},
"tsx": {
"optional": true
},
"yaml": {
"optional": true
}
}
},
"node_modules/postcss-nested": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/postcss-nested/-/postcss-nested-6.2.0.tgz",
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"postcss-selector-parser": "^6.1.1"
},
"engines": {
"node": ">=12.0"
},
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
"dev": true,
"dependencies": {
"pify": "^2.3.0"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz",
"integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
"dev": true,
"dependencies": {
"is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sucrase": {
"version": "3.35.1",
"resolved": "https://registry.npmmirror.com/sucrase/-/sucrase-3.35.1.tgz",
"integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
"lines-and-columns": "^1.1.6",
"mz": "^2.7.0",
"pirates": "^4.0.1",
"tinyglobby": "^0.2.11",
"ts-interface-checker": "^0.1.9"
},
"bin": {
"sucrase": "bin/sucrase",
"sucrase-node": "bin/sucrase-node"
},
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/tailwindcss": {
"version": "3.4.19",
"resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-3.4.19.tgz",
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
"dev": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
"chokidar": "^3.6.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.3.2",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.21.7",
"lilconfig": "^3.1.3",
"micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
"picocolors": "^1.1.1",
"postcss": "^8.4.47",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
"postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
"postcss-nested": "^6.2.0",
"postcss-selector-parser": "^6.1.2",
"resolve": "^1.22.8",
"sucrase": "^3.35.0"
},
"bin": {
"tailwind": "lib/cli.js",
"tailwindcss": "lib/cli.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
"dev": true,
"dependencies": {
"any-promise": "^1.0.0"
}
},
"node_modules/thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
}
}
"name": "ykt-wxapp",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ykt-wxapp",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"dayjs": "^1.11.10"
},
"devDependencies": {}
},
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz",
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
}
}
}

View File

@ -1,21 +1,21 @@
{
"pages": [
{
"path": "pages/home/home",
"path": "pages/message/message",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
"navigationBarTitleText": "消息"
}
},
{
"path": "pages/login/login",
"path": "pages/case/case",
"style": {
"navigationBarTitleText": "柚健康"
"navigationBarTitleText": "病例"
}
},
{
"path": "pages/login/redirect-page",
"path": "pages/work/work",
"style": {
<<<<<<< HEAD
"navigationBarTitleText": "柚健康"
}
},
@ -37,6 +37,24 @@
"navigationBarTitleText": "健康宣教"
}
},
{
"path": "pages/health/list",
"style": {
"navigationBarTitleText": "健康信息"
}
},
{
"path": "pages/health/record",
"style": {
"navigationBarTitleText": "健康信息"
}
},
{
"path": "pages/library/diagnosis-list",
"style": {
"navigationBarTitleText": "选择诊断"
}
},
{
"path": "pages/team/team-detail",
"style": {
@ -53,6 +71,9 @@
"path": "pages/team/friend",
"style": {
"navigationBarTitleText": "添加好友"
=======
"navigationBarTitleText": "工作台"
>>>>>>> e838f8af157c539c27370cbdd7d4a3bbc09e184b
}
}
],
@ -62,5 +83,31 @@
"navigationBarBackgroundColor": "#065bd6",
"backgroundColor": "#065bd6"
},
"tabBar": {
"color": "#666666",
"selectedColor": "#007aff",
"backgroundColor": "#ffffff",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/message/message",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home_selected.png",
"text": "消息"
},
{
"pagePath": "pages/case/case",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart_selected.png",
"text": "病例"
},
{
"pagePath": "pages/work/work",
"iconPath": "static/tabbar/center.png",
"selectedIconPath": "static/tabbar/center_selected.png",
"text": "工作台"
}
]
},
"uniIdRouter": {}
}

8
pages/case/case.vue Normal file
View File

@ -0,0 +1,8 @@
<template>
<div>case</div>
</template>
<script>
</script>
<style>
</style>

View File

@ -1,106 +1,278 @@
<template>
<full-page :customScroll="empty">
<view v-if="customers.length === 0" class="flex items-center justify-center h-full">
<template #header>
<view class="flex items-center bg-white text-base px-15 py-12">
<view class="flex-shrink-0 mr-5 text-gray">档案所属人</view>
<view class="text-dark">{{ name }}</view>
</view>
<view class="flex items-center py-12 px-15">
<view class="min-w-90 flex items-center bg-white rounded-sm px-10 mr-5" @click="selectType()">
<view class="leading-normal text-base py-5 px-10 text-dark mr-5">
{{ tempType[type] || '全部' }}
</view>
<uni-icons type="down" size="16" color="#666" />
</view>
<view class="w-100 flex items-center bg-white rounded-sm mr-5">
<uni-datetime-picker v-model="dates" type="daterange">
<view class="flex items-center rounded-sm mr-5 px-10 bg-white">
<view class="flex-grow w-0 text-dark truncate leading-normal text-base py-5 mr-5">
{{ dates.length ? dates.join(' ~ ') : '时间筛选' }}
</view>
<uni-icons type="down" size="16" color="#666" />
</view>
</uni-datetime-picker>
</view>
<view class="flex-grow"></view>
</view>
</template>
<view v-if="list.length === 0" class="flex items-center justify-center h-full">
<empty-data />
</view>
<view class="p-15">
<view v-for="customer in customers" :key="customer._id" class="bg-white rounded shadow-lg mb-10">
<view class="flex items-center px-15 py-12 border-b">
<view class="flex-shrink-0 mr-5 text-lg text-dark font-semibold">{{ customer.name }}</view>
<view v-if="customer.relationship"
class="flex-shrink-0 mr-5 border-primary text-primary px-10 text-sm leading-normal rounded-sm">
{{ customer.relationship }}
<view v-else class="px-15 pb-15">
<!-- v-for="customer in list" :key="customer._id" -->
<view v-for="i in list" :key="i._id" class="bg-white rounded shadow-lg mb-10"
@click="toRecord(i.medicalType, i._id)">
<view class="flex items-center py-12 px-15">
<view class="text-lg font-semibold text-dark mr-5">
{{ i.date }}
</view>
<view class="flex-grow mr-5"></view>
<view v-if="enableHis && customer.isConnectHis"
class="px-15 py-5 text-sm leading-normal bg-success text-white rounded-sm">
未关联档案
<view v-if="i.medicalType === 'outpatient'"
class="mr-5 px-10 leading-normal text-white text-base bg-warning rounded-full">门诊信息</view>
<view v-else-if="i.medicalType === 'inhospital'"
class="mr-5 px-10 leading-normal text-white text-base bg-success rounded-full">住院信息</view>
<view v-if="i.corp === '其他'" class="px-10 leading-normal text-white text-base bg-danger rounded-full">
外院
</view>
<view v-else-if="enableHis" class="px-15 py-5 text-sm leading-normal bg-warning text-white rounded-sm">未关联档案
<view class="flex-grow"></view>
<view class="flex items-center text-base text-primary">
<view class="mr-5">查看详情</view>
<uni-icons type="right" :size="14" color="#0074ff" />
</view>
</view>
<view class="px-15 py-12 border-b">
<view class="text-base leading-normal">
<text v-if="customer.sex"> {{ customer.sex }}</text>
<text v-if="customer.sex && customer.age">/</text>
<text v-if="customer.age"> {{ customer.age }}</text>
<text v-if="customer.sex || customer.age"></text>
<text v-if="customer.mobile"> {{ customer.mobile }}</text>
<view v-if="i.rows.length" class="px-15 border-b">
<view v-for="row in i.rows" :key="row.key" class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 w-90 text-base text-gray">{{ row.label }}</view>
<view v-if="row.title === 'diagnosisName'" class="w-0 flex-grow text-base text-dark">
{{ row.value && row.value.join ? row.value.join(', ') : '' }}
</view>
<view v-else-if="row.title === 'files'" class="w-0 flex-grow text-base text-dark">
<view v-if="row.value && row.value.length" class="w-full flex flex-wrap">
<image v-for="file in row.value" :src="file.url" class="file-icon" @click.stop="preview(file)" />
</view>
</view>
<view v-else class="w-0 flex-grow text-base text-dark">
{{ row.value }}
</view>
</view>
<view class="text-base leading-normal">证件号{{ customer.idCard || '--' }}</view>
<!-- <view class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 w-90 text-base text-gray">临床诊断</view>
<view class="w-0 flex-grow text-base text-dark">龋齿</view>
</view>
<view class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 w-90 text-base text-gray">临床诊断</view>
<view class="w-0 flex-grow text-base text-dark">龋齿</view>
</view> -->
</view>
<view class="px-15 py-12 flex justify-end">
<view v-if="enableHis && !customer.isConnectHis" class="mr-10 text-base text-primary">关联档案</view>
<view class="mr-10 text-base text-success" @click="changeArchive(customer)">完善个人信息</view>
<view class="mr-10 text-base text-danger" @click="unBindArchive(customer)">删除档案</view>
<view v-if="i.dataSource === 'customerReport'" class="px-15 py-12 text-base text-dark">
记录时间{{ i.createTime }} 记录人自己
</view>
</view>
</view>
<template #footer>
<button-footer confirmText="新增档案" :showCancel="false" @confirm="addArchive()" />
<button-footer v-if="healthTempList.length" confirmText="+新增健康档案" :showCancel="false" @confirm="addArchive()" />
</template>
</full-page>
</template>
<script setup>
import { ref } from 'vue';
import { storeToRefs } from 'pinia'
import { computed, ref, watch } from 'vue';
import dayjs from 'dayjs';
import useGuard from '@/hooks/useGuard';
import useAccount from '@/store/account';
import api from '@/utils/api';
import ButtonFooter from '@/components/button-footer.vue';
import EmptyData from '@/components/empty-data.vue';
import FullPage from '@/components/full-page.vue';
import { confirm, toast } from '../../utils/widget';
import { toast } from '../../utils/widget';
const tempType = {
outpatient: '门诊信息',
inhospital: '住院信息'
}
const empty = ref(false)
const { useLoad, useShow } = useGuard();
const { account } = storeToRefs(useAccount());
const corpId = ref('');
const customerId = ref('');
const dates = ref([])
const list = ref([]);
const name = ref('');
const team = ref(null);
const type = ref('all');
const teamId = ref('');
const enableHis = ref(false);
const customers = ref([]);
const page = ref(1);
const more = ref(false)
const loading = ref(false);
const qrcode = computed(() => team.value && Array.isArray(team.value.qrcodes) ? team.value.qrcodes[0] : null)
const healthTempList = computed(() => qrcode.value && Array.isArray(qrcode.value.healthTempList) ? qrcode.value.healthTempList.map(i => ({ label: tempType[i.templateType], value: i.templateType })).filter(i => i.label) : [])
const tempShowField = ref(null);
const config = {
outpatient: ["corp", "deptName", "doctor", "diagnosisName", "files"],
inhospital: ["corp", "diagnosisName", "operation", "operationDate", "outhosDate", "files"],
};
function addArchive() {
uni.navigateTo({
url: `/pages/archive/edit-archive?teamId=${teamId.value}&corpId=${corpId.value}`
})
}
function changeArchive(customer) {
uni.navigateTo({
url: `/pages/archive/edit-archive?teamId=${teamId.value}&corpId=${corpId.value}&id=${customer._id}`
})
}
async function getMembers() {
const res = await api('getTeamCustomers', { corpId: corpId.value, teamId: teamId.value, miniAppId: account.value.openid });
customers.value = res && Array.isArray(res.data) ? res.data : [];
// enableHis.value = res && typeof res.enableHis === 'boolean' ? res.enableHis : false;
if (!res || !res.data) {
toast(res?.message || '获取档案信息失败')
if (healthTempList.value.length > 1) {
uni.showActionSheet({
title: '选择新增档案类型',
itemList: healthTempList.value.map(i => i.label),
success: function (res) {
toRecord(healthTempList.value[res.tapIndex].value)
}
});
} else {
toRecord(healthTempList.value[0].value)
}
}
async function unBindArchive(customer) {
await confirm('确定删除档案吗?')
const res = await api('unbindMiniAppArchive', { id: customer._id, corpId: corpId.value, teamId: teamId.value, miniAppId: account.value.openid });
if (res && res.success) {
await toast('删除成功');
getMembers();
function getTempRows(type, data) {
if (config[type] && tempShowField.value && tempShowField.value[type]) {
const list = [];
config[type].forEach(i => {
if (tempShowField.value[type][i]) {
list.push({ title: i, label: tempShowField.value[type][i], value: data[i], key: `${i}_${data._id}` })
}
})
return list;
}
return []
}
function toRecord(type, id = '') {
uni.navigateTo({
url: `/pages/health/record?type=${type}&teamId=${teamId.value}&corpId=${corpId.value}&id=${id}&customerId=${customerId.value}`
})
}
function preview(file) {
if (/image/i.test(file.type)) {
uni.previewImage({
urls: [file.url]
})
}
}
function selectType() {
const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value]
uni.showActionSheet({
title: '选择新增档案类型',
itemList: itemList.map(i => i.label),
success: function (res) {
type.value = itemList[res.tapIndex].value;
page.value = 1;
getList()
}
});
}
async function getTeam() {
const res = await api('getTeamData', { teamId: teamId.value, corpId: corpId.value });
if (res && res.data) {
team.value = res.data;
} else {
toast(res?.message || '删除失败')
toast(res?.message || '获取团队信息失败')
}
}
async function getList() {
if (!tempShowField.value) {
await getTeamHealthTemps()
}
if (loading.value) return;
const params = {
corpId: corpId.value,
memberId: customerId.value,
page: page.value,
pageSize: 20,
medicalType: ['outpatient', 'inhospital']
}
if (type.value !== 'all') {
params.medicalType = [type.value]
}
if (dates.value.length) {
params.startTime = dates.value[0];
params.endTime = dates.value[1];
}
loading.value = true;
const res = await api('getCustomerMedicalRecord', params);
loading.value = false;
const arr = res && Array.isArray(res.list) ? res.list.map(i => ({
...i,
date: i.sortTime && dayjs(i.sortTime).isValid ? dayjs(i.sortTime).format('YYYY-MM-DD') : '',
createTime: i.createTime && dayjs(i.createTime).isValid ? dayjs(i.createTime).format('YYYY-MM-DD HH:mm') : '',
rows: getTempRows(i.medicalType, i)
})) : [];
list.value = page.value === 1 ? arr : [...list.value, ...arr];
more.value = page.value < res.pages;
console.log(list.value)
}
async function getTeamHealthTemps() {
const res = await api('getTeamHealthTemps', { teamId: teamId.value, corpId: corpId.value });
if (res && res.success) {
const arr = res && Array.isArray(res.data) ? res.data : [];
tempShowField.value = arr.reduce((m, item) => {
const templateList = Array.isArray(item.templateList) ? item.templateList : [];
const data = {}
templateList.forEach(i => (data[i.title] = i.name));
m[item.templateType] = data
return m
}, {})
} else {
toast(res?.message || '获取团队健康档案模板失败');
return Promise.reject()
}
}
useLoad(options => {
name.value = decodeURIComponent(options.name || '');
teamId.value = options.teamId;
corpId.value = options.corpId;
customerId.value = options.id || '';
getTeam()
// getTeamHealthTemps();
})
useShow(() => {
if (teamId.value && corpId.value) {
getMembers()
}
page.value = 1;
getList()
})
watch(dates, n => {
page.value = 1;
getList()
})
</script>
<style>
.min-w-90 {
min-width: 180rpx;
}
.w-90 {
width: 160rpx;
}
.w-100 {
width: 240rpx;
}
.whitespace-nowrap {
white-space: nowrap;
}
.file-icon {
margin-right: 10rpx;
margin-bottom: 10rpx;
width: 80rpx;
height: 80rpx;
}
</style>

176
pages/health/record.vue Normal file
View File

@ -0,0 +1,176 @@
<template>
<full-page v-if="!visible">
<view v-if="formItems.length === 0" class="flex items-center justify-center h-full">
<empty-data />
</view>
<view v-else class="p-15" :class="canEdit ? '' : 'disabled'">
<view class="bg-white rounded shadow-lg">
<form-template ref="tempRef" :items="displayFormItems" :form="formData" @change="change($event)" />
</view>
</view>
<template #footer>
<button-footer v-if="canEdit" confirmText="保存" :showCancel="false" @confirm="confirm()" />
</template>
</full-page>
</template>
<script setup>
import { computed, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { onLoad } from "@dcloudio/uni-app";
import dayjs from 'dayjs';
import useGuard from '@/hooks/useGuard';
import useAccount from '@/store/account';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
import ButtonFooter from '@/components/button-footer.vue';
import EmptyData from '@/components/empty-data.vue';
import FullPage from '@/components/full-page.vue';
import formTemplate from '@/components/form-template/index.vue';
const { useLoad } = useGuard();
const { account } = storeToRefs(useAccount());
const corpId = ref('');
const customerId = ref('');
const id = ref('');
const form = ref({});
const record = ref({});
const formItems = ref([]);
const teamId = ref('');
const tempRef = ref(null);
const type = ref('');
const visible = ref(false);
const timeTitle = ref('');
const canEdit = ref(false)
const formData = computed(() => ({ ...record.value, ...form.value }));
const displayFormItems = computed(() => {
const list = formItems.value.map(i => {
const item = { ...i };
if (i.referenceField && i.referenceValue) {
item.displayRow = formData.value[i.referenceField] === i.referenceValue;
} else {
item.displayRow = true
}
return item
})
return list.filter(i => i.displayRow);
})
function change({ title, value }) {
if (title) {
form.value[title] = value;
}
}
function confirm() {
if (!tempRef.value.verify() || Object.keys(form.value).length === 0) return;
if (id.value) {
updateHealthRecord();
} else {
addHealthRecord()
}
}
async function addHealthRecord() {
const data = {
...form.value,
corpId: corpId.value,
memberId: customerId.value,
// teamId: teamId.value,
dataSource: 'customerReport',
miniAppId: account.value.openid,
medicalType: type.value
}
if (timeTitle.value) {
data.sortTime = data[timeTitle.value] && dayjs(data[timeTitle.value]).isValid() ? dayjs(data[timeTitle.value]).valueOf() : dayjs().valueOf();
}
const res = await api('addMedicalRecord', data);
if (res && res.success) {
await toast('保存成功');
uni.navigateBack();
} else {
toast(res?.message || '保存失败');
}
}
async function updateHealthRecord() {
if (Object.keys(form.value).length === 0) {
uni.navigateBack();
return;
};
const data = {
...form.value,
_id: id.value,
corpId: corpId.value,
memberId: customerId.value,
miniAppId: account.value.openid,
medicalType: type.value
}
if (timeTitle.value) {
data.sortTime = formData.value[timeTitle.value] && dayjs(formData.value[timeTitle.value]).isValid() ? dayjs(formData.value[timeTitle.value]).valueOf() : dayjs().valueOf();
}
const res = await api('updateMedicalRecord', data);
if (res && res.success) {
await toast('保存成功');
uni.navigateBack();
} else {
toast(res?.message || '保存失败');
}
}
async function init() {
await getBaseForm();
if (id.value) {
getRecord()
} else {
canEdit.value = true
}
}
async function getBaseForm() {
const res = await api('getTeamHealthTemplate', { corpId: corpId.value, teamId: teamId.value, templateType: type.value });
if (res && res.success) {
formItems.value = Array.isArray(res.data) ? res.data : [];
timeTitle.value = typeof res.timeTitle === 'string' ? res.timeTitle : '';
} else {
toast(res?.message || '查询失败');
return Promise.reject()
}
}
async function getRecord() {
const res = await api('getMedicalRecordById', {
corpId: corpId.value,
memberId: customerId.value,
_id: id.value,
medicalType: type.value
});
if (res && res.success) {
record.value = res.record
canEdit.value = record.value.dataSource === 'customerReport'
} else {
await toast(res?.message || '查询失败');
uni.navigateBack();
}
}
onLoad(options => {
type.value = options.type;
id.value = options.id || '';
customerId.value = options.customerId || '';
corpId.value = options.corpId;
teamId.value = options.teamId;
uni.setNavigationBarTitle({ title: id.value ? '编辑健康档案' : '新增健康档案' })
})
useLoad(options => {
init();
})
</script>
<style scoped>
.disabled {
pointer-events: none;
}
</style>

View File

@ -54,12 +54,12 @@
<view class="text-base text-gray">基础信息填写</view>
</view>
<!-- v-if="healthTempList && healthTempList.length" -->
<view class="flex-grow p-10 rounded bg-gray" @click="toHospitalList()">
<view class="flex-grow p-10 rounded bg-gray" @click="toHealthList()">
<view class="flex items-center justify-between mb-5">
<view class="text-lg">个人住院信息</view>
<view class="text-lg">个人健康信息</view>
<uni-icons color="#999" type="arrowright"></uni-icons>
</view>
<view class="text-base text-gray">住院信息列表</view>
<view class="text-base text-gray">健康信息列表</view>
</view>
</view>
</view>
@ -103,8 +103,18 @@ function fillBaseInfo() {
toast('请先授权本服务团队')
} else {
uni.navigateTo({
url: `/pages/archive/edit-archive?teamId=${props.team.teamId}&corpId=${props.corpId}&id=${current.value._id}`,
complete: console.log
url: `/pages/archive/edit-archive?teamId=${props.team.teamId}&corpId=${props.corpId}&id=${current.value._id}`
})
}
}
function toHealthList() {
if (canAuth.value) {
toast('请先授权本服务团队')
} else {
const name = `${current.value.name} ${current.value.relationship ? `(${current.value.relationship})` : ''}`
uni.navigateTo({
url: `/pages/health/list?teamId=${props.team.teamId}&corpId=${props.corpId}&id=${current.value._id}&name=${encodeURIComponent(name)}`
})
}
}

View File

@ -0,0 +1,159 @@
<template>
<full-page>
<template #header>
<view class="page-item border-bottom bg-white">
<input class="search-input" placeholder-style="font-size:28rpx" placeholder="请搜索名称" v-model="name"
@input="search" />
</view>
</template>
<view v-for="i in list" :key="i.label" class="search-item bg-white" @click="select(i.label)">
<view class="name">{{ i.label }}</view>
<icon class="icon-checked" :class="selectMap[i.label] ? '' : 'hidden'" type="success_no_circle" size="18" />
</view>
<template #footer>
<button-footer confirmText="确定" :showCancel="false" @confirm="confirm()" />
</template>
</full-page>
</template>
<script setup>
import { computed, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { onLoad } from "@dcloudio/uni-app";
import api from '@/utils/api';
import { remove, get } from '@/utils/cache';
import useDebounce from '@/utils/useDebounce';
import { toast } from '@/utils/widget';
import ButtonFooter from '@/components/button-footer.vue';
import FullPage from '@/components/full-page.vue';
const name = ref('');
const list = ref([]);
const page = ref(1);
const pageSize = ref(30);
const more = ref(false);
const selections = ref([]);
const eventName = ref('')
const selectMap = computed(() => selections.value.reduce((val, i) => {
i && (val[i] = i);
return val
}, {}))
const search = useDebounce(() => {
page.value = 1;
getList()
})
function confirm() {
if (selections.value.length) {
uni.$emit(eventName.value, selections.value);
uni.navigateBack()
} else {
toast('请选择疾病')
}
}
function select(label) {
if (selections.value.includes(label)) {
selections.value = selections.value.filter(i => i !== label)
} else {
selections.value.push(label)
}
}
async function getList() {
const res = await api('getPageDisease', { name: name.value.trim(), page: page.value, pageSize: pageSize.value });
const diseases = res && Array.isArray(res.list) ? res.list.map(i => ({
label: i.diseaseName,
value: i.diseaseName
})).filter(i => i.label !== name.value.trim()) : [];
const pages = res && res.pages ? res.pages : 0;
more.value = pages > page.value;
if (page.value === 1) {
const data = name.value.trim() ? [{
label: name.value.trim(),
value: name.value.trim()
}] : [];
data.push(...diseases);
list.value = data
} else {
list.value = [...list.value, ...diseases];
}
}
onLoad(options => {
eventName.value = options.eventName;
const data = get('diagnosis-list-selections');
selections.value = Array.isArray(data) ? data : [];
remove('diagnosis-list-selections');
if (selections.value.length) {
list.value = selections.value.map(i => ({
label: i,
value: i
}))
} else {
getList()
}
})
</script>
<style scoped lang="scss">
.hidden {
opacity: 0;
}
.border-bottom {
border-bottom: 1px solid #eee;
}
.border-top {
border-top: 1px solid #eee;
}
.list-page {
display: flex;
flex-direction: column;
height: 100%;
height: 100vh;
}
.search-input {
border: 1px solid #eee;
padding: 16rpx 20rpx;
border-radius: 12rpx;
font-size: 28rpx;
}
.scroll-wrapper {
position: relative;
flex-grow: 1;
}
.list-scroll {
position: absolute;
inset: 0;
}
.search-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
border-bottom: 1px solid #eee;
}
.icon-checked {
flex-shrink: 0;
}
.name {
flex-grow: 1;
margin-right: 20rpx;
font-size: 28rpx;
}
.page-item {
flex-shrink: 0;
padding: 30rpx;
}
</style>

View File

@ -1,143 +1,156 @@
<template>
<view v-if="team" class="pt-lg px-15 flex flex-col items-center text-center">
<group-avatar :avatarList="team.avatars" />
<view class="mt-15 text-base font-semibold text-dark">{{ team.teamName }}</view>
<view class="mt-12 text-sm text-gray">{{ team.corpName }}</view>
<view class="mt-15 text-lg text-dark font-semibold">为您提供团队个性化专属服务</view>
</view>
<view v-else class="pt-lg px-15 flex flex-col items-center text-center">
<image src="/static/logo-plain.png" class="logo"></image>
<view class="mt-15 text-xl font-semibold text-dark">柚健康</view>
<view class="mt-12 text-base text-dark">生命全周期健康管理伙伴</view>
</view>
<view class="login-btn-wrap">
<!-- <button v-if="checked" class="login-btn" type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
<view v-if="team" class="pt-lg px-15 flex flex-col items-center text-center">
<group-avatar :avatarList="team.avatars" />
<view class="mt-15 text-base font-semibold text-dark">{{
team.teamName
}}</view>
<view class="mt-12 text-sm text-gray">{{ team.corpName }}</view>
<view class="mt-15 text-lg text-dark font-semibold"
>为您提供团队个性化专属服务</view
>
</view>
<view v-else class="pt-lg px-15 flex flex-col items-center text-center">
<image src="/static/logo-plain.png" class="logo"></image>
<view class="mt-15 text-xl font-semibold text-dark">柚健康</view>
<view class="mt-12 text-base text-dark">生命全周期健康管理伙伴</view>
</view>
<view class="login-btn-wrap">
<button
v-if="checked"
class="login-btn"
type="primary"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>
手机号快捷登录
</button>
<!-- <button v-if="checked" class="login-btn" type="primary" @click="getPhoneNumber()">
手机号快捷登录
</button> -->
<button v-if="checked" class="login-btn" type="primary" @click="getPhoneNumber()">
手机号快捷登录
</button>
<button v-else class="login-btn" type="primary" @click="remind()">
手机号快捷登录
</button>
</view>
<view class="flex items-center justify-center mt-12 px-15" @click="checked = !checked">
<checkbox :checked="checked" style="transform:scale(0.7)" />
<view class="text-sm text-gray">我已阅读并同意</view>
<view class="text-sm text-primary">用户协议</view>
<view class="text-sm text-primary">隐私政策</view>
</view>
<button v-else class="login-btn" type="primary" @click="remind()">
手机号快捷登录
</button>
</view>
<view
class="flex items-center justify-center mt-12 px-15"
@click="checked = !checked"
>
<checkbox :checked="checked" style="transform: scale(0.7)" />
<view class="text-sm text-gray">我已阅读并同意</view>
<view class="text-sm text-primary">用户协议</view>
<view class="text-sm text-primary">隐私政策</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import useAccountStore from '@/store/account';
import useAccountStore from "@/store/account";
import { get } from "@/utils/cache";
import { toast } from '@/utils/widget';
import { toast } from "@/utils/widget";
import groupAvatar from '@/components/group-avatar.vue';
import groupAvatar from "@/components/group-avatar.vue";
const team = ref(true)
const checked = ref(false)
const redirectUrl = ref('')
const team = ref(true);
const checked = ref(false);
const redirectUrl = ref("");
const { login } = useAccountStore();
function attempRedirect(url) {
return new Promise((resolve, reject) => {
uni.redirectTo({
url,
success: () => resolve(true),
fail: () => reject(false)
})
})
return new Promise((resolve, reject) => {
uni.redirectTo({
url,
success: () => resolve(true),
fail: () => reject(false),
});
});
}
function attempSwitchTab(url) {
return new Promise((resolve, reject) => {
uni.switchTab({
url,
success: () => resolve(true),
fail: () => reject(false)
})
})
return new Promise((resolve, reject) => {
uni.switchTab({
url,
success: () => resolve(true),
fail: () => reject(false),
});
});
}
function remind() {
toast('请先阅读并同意用户协议和隐私政策');
toast("请先阅读并同意用户协议和隐私政策");
}
function toHome() {
uni.navigateTo({
url: '/pages/home/home'
})
uni.navigateTo({
url: "/pages/home/home",
});
}
async function getPhoneNumber(e) {
const phoneCode = e && e.detail && e.detail.code;
if (e && !phoneCode) return;
const res = await login(phoneCode);
if (res && redirectUrl.value) {
await attempToPage(redirectUrl.value)
} else if (res) {
toHome()
}
const phoneCode = e && e.detail && e.detail.code;
if (e && !phoneCode) return;
const res = await login(phoneCode);
if (res && redirectUrl.value) {
await attempToPage(redirectUrl.value);
} else if (res) {
toHome();
}
}
async function attempToPage(url) {
const res1 = attempRedirect(url);
if (res1) return;
const res2 = attempSwitchTab(url);
if (res2) return;
toHome()
const res1 = attempRedirect(url);
if (res1) return;
const res2 = attempSwitchTab(url);
if (res2) return;
toHome();
}
onLoad(opts => {
if (opts.source === 'teamInvite') {
team.value = get('invite-team-info');
redirectUrl.value = `/pages/archive/edit-archive?teamId=${team.value.teamId}&corpId=${team.value.corpId}`
console.log('redirectUrl', redirectUrl.value)
return
}
redirectUrl.value = opts.redirectUrl || '';
})
onLoad((opts) => {
if (opts.source === "teamInvite") {
team.value = get("invite-team-info");
redirectUrl.value = `/pages/archive/edit-archive?teamId=${team.value.teamId}&corpId=${team.value.corpId}`;
console.log("redirectUrl", redirectUrl.value);
return;
}
redirectUrl.value = opts.redirectUrl || "";
});
</script>
<style scoped>
.pt-lg {
padding-top: 20vh;
padding-top: 20vh;
}
.logo {
width: 160rpx;
height: 160rpx;
width: 160rpx;
height: 160rpx;
}
.login-btn-wrap {
width: 100vw;
display: flex;
justify-content: center;
margin-top: 80rpx;
width: 100vw;
display: flex;
justify-content: center;
margin-top: 80rpx;
}
.login-btn-wrap-loading {
pointer-events: none;
pointer-events: none;
}
.login-btn {
width: calc(100vw - 112rpx);
max-width: 600rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
color: #fff;
font-size: 30rpx;
border-radius: 48rpx;
font-weight: 600;
box-shadow: 0 4rpx 16rpx rgba(59, 124, 255, 0.08);
border: none;
width: calc(100vw - 112rpx);
max-width: 600rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
color: #fff;
font-size: 30rpx;
border-radius: 48rpx;
font-weight: 600;
box-shadow: 0 4rpx 16rpx rgba(59, 124, 255, 0.08);
border: none;
}
.login-btn:active {
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
}
</style>

View File

@ -38,10 +38,19 @@ async function changeTeam({ teamId, corpId, corpName }) {
}
onLoad(options => {
teamId.value = options.teamId || '';
corpId.value = options.corpId || '';
changeTeam({ teamId: teamId.value, corpId: corpId.value });
const href = typeof options.q === 'string' ? decodeURIComponent(options.q) : '';
const [, url = ''] = href.split('?');
const data = url.split('&').reduce((acc, cur) => {
console.log(cur)
const [key, value] = cur.split('=');
console.log(key, '=====', value)
acc[key] = value;
return acc;
}, {})
changeTeam(data)
})
</script>
<style>
.flash-logo {

View File

@ -0,0 +1,9 @@
<template>
<div>message</div>
</template>
<script>
</script>
<style>
</style>

9
pages/work/work.vue Normal file
View File

@ -0,0 +1,9 @@
<template>
<div>work</div>
</template>
<script>
</script>
<style>
</style>

View File

@ -28,6 +28,14 @@ export default [
path: 'pages/health/list',
meta: { title: '健康信息', login: true }
},
{
path: 'pages/health/record',
meta: { title: '健康信息', login: true }
},
{
path: 'pages/library/diagnosis-list',
meta: { title: '选择诊断' }
},
{
path: 'pages/team/team-detail',
meta: { title: '团队介绍', login: true }

1
static/file.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1768890544193" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9729" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M 518.72 238.4 l -84.8 -95.68 c -8 -9.28 -20.16 -14.72 -32.64 -14.72 H 74.56 C 50.24 128 30.4 147.52 30.4 171.84 v 696.64 c 0 24.32 19.52 43.84 43.84 43.84 H 969.6 c 24.32 0 43.84 -19.52 43.84 -43.84 V 297.28 c 0 -24.32 -19.52 -43.84 -43.84 -43.84 H 551.68 c -12.48 0 -24.64 -5.44 -32.96 -15.04 Z" fill="#06a8f5" p-id="9730"></path></svg>

After

Width:  |  Height:  |  Size: 671 B

BIN
static/tabbar/cart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
static/tabbar/center.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
static/tabbar/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -7,19 +7,26 @@ const urlsConfig = {
getTeamData: 'getTeamData',
queryWxJoinedTeams: 'queryWxJoinedTeams',
wxAppLogin: 'wxAppLogin',
getTeamHealthTemplate: 'getTeamHealthTemplate',
getTeamHealthTemps: "getTeamHealthTemps",
},
knowledgeBase: {
getArticleByIds: 'getArticleByIds'
getArticleByIds: 'getArticleByIds',
getPageDisease: "getPageDisease"
},
member: {
addCustomer: 'add',
addMedicalRecord: 'addMedicalRecord',
bindMiniAppArchive: "bindMiniAppArchive",
getCustomerByCustomerId: 'getCustomerByCustomerId',
getMiniAppCustomers: 'getMiniAppCustomers',
getTeamCustomers: 'getTeamCustomers',
getUnbindMiniAppCustomers: 'getUnbindMiniAppCustomers',
getCustomerMedicalRecord: 'getCustomerMedicalRecord',
getMedicalRecordById: 'getMedicalRecordById',
unbindMiniAppArchive: 'unbindMiniAppArchive',
updateMedicalRecord: 'updateMedicalRecord'
},
wecom: {
addContactWay: 'addContactWay'
@ -38,7 +45,6 @@ const urls = Object.keys(urlsConfig).reduce((acc, path) => {
})
return acc
}, {})
console.log('urls: ', urls)
export default async function api(urlId, data) {
const config = urls[urlId];

View File

@ -202,5 +202,28 @@ export default request;
export const uploadUrl = `${baseUrl}/upload`;
export function getFullPath(path) {
return `${baseUrl}${path}`;
return `${baseUrl}/${path}`;
}
export function upload(path) {
return new Promise((resolve) => {
uni.uploadFile({
url: uploadUrl, // 替换为你的上传接口地址
filePath: path,
name: 'file',
fileType: 'image',
success: (res) => {
try {
const url = JSON.parse(res.data).filePath;
resolve(url ? getFullPath(url) : '')
} catch (e) {
resolve()
}
},
fail: res => {
resolve()
}
})
})
}