This commit is contained in:
wangdongbo 2026-01-20 10:49:33 +08:00
parent daf049cb5a
commit e838f8af15
30 changed files with 200 additions and 2957 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"
}
]
}

933
package-lock.json generated
View File

@ -11,943 +11,12 @@
"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"
}
"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=="
},
"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
}
}
}

View File

@ -1,58 +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": {
"navigationBarTitleText": "柚健康"
}
},
{
"path": "pages/archive/archive-manage",
"style": {
"navigationBarTitleText": "档案管理"
}
},
{
"path": "pages/archive/edit-archive",
"style": {
"navigationBarTitleText": "新增档案"
}
},
{
"path": "pages/article/article-list",
"style": {
"navigationBarTitleText": "健康宣教"
}
},
{
"path": "pages/team/team-detail",
"style": {
"navigationBarTitleText": "团队介绍"
}
},
{
"path": "pages/team/homepage",
"style": {
"navigationBarTitleText": "个人主页"
}
},
{
"path": "pages/team/friend",
"style": {
"navigationBarTitleText": "添加好友"
"navigationBarTitleText": "工作台"
}
}
],
@ -62,5 +25,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": {}
}

View File

@ -1,106 +0,0 @@
<template>
<full-page :customScroll="empty">
<view v-if="customers.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>
<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>
<view v-else-if="enableHis" class="px-15 py-5 text-sm leading-normal bg-warning text-white rounded-sm">未关联档案
</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>
<view class="text-base leading-normal">证件号{{ customer.idCard || '--' }}</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>
</view>
</view>
<template #footer>
<button-footer confirmText="新增档案" :showCancel="false" @confirm="addArchive()" />
</template>
</full-page>
</template>
<script setup>
import { ref } from 'vue';
import { storeToRefs } from 'pinia'
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';
const empty = ref(false)
const { useLoad, useShow } = useGuard();
const { account } = storeToRefs(useAccount());
const corpId = ref('');
const teamId = ref('');
const enableHis = ref(false);
const customers = ref([]);
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 || '获取档案信息失败')
}
}
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();
} else {
toast(res?.message || '删除失败')
}
}
useLoad(options => {
teamId.value = options.teamId;
corpId.value = options.corpId;
})
useShow(() => {
if (teamId.value && corpId.value) {
getMembers()
}
})
</script>

View File

@ -1,98 +0,0 @@
<template>
<uni-popup ref="popup" type="center" :mask-click="false">
<view class="bg-white rounded overflow-hidden" style="width: 690rpx;">
<view class="flex items-center justify-between px-15 py-12 border-b">
<view class="text-lg font-semibold text-dark">通过档案手机号验证</view>
<uni-icons type="closeempty" :size="24" color="#999" @click="close"></uni-icons>
</view>
<view class="px-15 pt-15 text-base text-dark">
您在{{ corpName }}医客通平台已存在档案请选择档案绑定
</view>
<scroll-view scroll-y="true" class="popup-content-scroll">
<view class="px-15 py-12">
<view v-for="customer in customers" :key="customer._id"
class="flex items-center p-10 mb-10 rounded-sm bg-gray" @click="id = customer._id">
<view class="flex-grow w-0 mr-5 text-base leading-normal text-dark">
<view class="flex items-center">
<view class="flex-shrink-0 min-w-60">姓名</view>
<view>{{ customer.name }}</view>
</view>
<view class="flex items-center">
<view class="flex-shrink-0 min-w-60">性别</view>
<view>{{ customer.sex || '--' }}</view>
</view>
<view class="flex items-center">
<view class="flex-shrink-0 min-w-60">手机号</view>
<view>{{ customer.mobile }}</view>
</view>
</view>
<image class="check-icon" :src="`/static/form/${id === customer._id ? 'checked' : 'uncheck'}.svg`"></image>
</view>
</view>
</scroll-view>
<view class="flex justify-end px-15 pb-10">
<view class="mr-5 text-base text-dark">以上档案都不对可以</view>
<view class="px-10 text-base leading-normal text-primary border-auto rounded-sm" @click="close()">新增档案</view>
</view>
<view class="footer-buttons">
<button-footer hideden-shadow confirmText="确定" :showCancel="false" @confirm="confirm()" />
</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref, watch } from 'vue';
import { toast } from '@/utils/widget';
import ButtonFooter from '@/components/button-footer.vue';
const emits = defineEmits(['close', 'confirm'])
const props = defineProps({
corpName: {
type: String,
default: ''
},
customers: {
type: Array,
default: () => []
},
visible: {
type: Boolean,
default: false
}
})
const popup = ref()
const id = ref('')
function close() {
emits('close')
}
function confirm() {
if (props.customers.some(i => i._id === id.value && id.value)) {
emits('confirm', id.value)
} else {
toast('请选择档案')
}
}
watch(() => props.visible, n => {
if (n) {
popup.value && popup.value.open()
} else {
popup.value && popup.value.close()
}
})
</script>
<style lang="scss" scoped>
.min-w-60 {
min-width: 120rpx;
}
.check-icon {
width: 48rpx;
height: 48rpx;
}
</style>

View File

@ -1,180 +0,0 @@
<template>
<full-page v-if="!visible" :customScroll="empty">
<view v-if="formItems.length === 0" class="flex items-center justify-center h-full">
<empty-data />
</view>
<view v-else class="p-15">
<view class="bg-white rounded shadow-lg">
<form-template ref="tempRef" :disableTitles="disableTitles" :items="formItems" :form="formData"
@change="change($event)" />
</view>
</view>
<template #footer>
<button-footer confirmText="新增档案" :showCancel="false" @confirm="confirm()" />
</template>
</full-page>
<bind-popup :customers="customers" :corpName="corpName" :visible="visible" @close="visible = false"
@confirm="bindArchive($event)" />
<verify-popup :visible="verifyVisible" @close="verifyVisible = false" />
</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 validate from '@/utils/validate';
import ButtonFooter from '@/components/button-footer.vue';
import EmptyData from '@/components/empty-data.vue';
import FullPage from '@/components/full-page.vue';
import bindPopup from './bind-popup.vue';
import verifyPopup from './verify-popup.vue';
import formTemplate from '@/components/form-template/index.vue';
const empty = ref(false)
const { useLoad } = useGuard();
const { account } = storeToRefs(useAccount());
const corpId = ref('');
const corpName = ref('');
const customer = ref({});
const customerId = ref('');
const customers = ref([]);
const disableTitles = ref(['mobile']);
const form = ref({});
const formItems = ref([]);
const loading = ref(false);
const teamId = ref('');
const tempRef = ref(null);
const customerArchive = ref(null);
const verifyVisible = ref(false);
const visible = ref(false);
const formData = computed(() => ({ ...customer.value, ...form.value }));
function back() {
const pages = getCurrentPages();
if (pages.length > 1) {
uni.navigateBack();
} else {
uni.redirectTo({ url: `/pages/home/home?corpId=${corpId.value}&teamId=${teamId.value}` })
}
}
function change({ title, value }) {
if (title) {
form.value[title] = value;
}
if (title !== 'idCard') return;
const [isIdCard, birthday, gender] = validate.isChinaId(value);
if (isIdCard) {
form.value.birthday = birthday;
form.value.sex = gender == 'MALE' ? '男' : '女';
const age = dayjs().diff(birthday, 'year');
form.value.age = Math.max(1, age);
}
}
function confirm() {
if (!tempRef.value.verify() || Object.keys(form.value).length === 0) return;
if (customerId.value) {
updateArchive();
} else {
addArchive();
}
}
async function addArchive() {
if (loading.value) return;
loading.value = true;
const params = {
...form.value,
addMethod: 'customerManual',
teamId: teamId.value,
corpId: corpId.value,
mobile: account.value.mobile,
miniAppId: account.value.openid
}
loading.value = false;
const res = await api('addCustomer', { params });
if (res && res.success) {
back()
} else {
toast(res?.message || '新增档案失败');
}
}
async function bindArchive(customerId) {
const res = await api('bindMiniAppArchive', { id: customerId, corpId: corpId.value, teamId: teamId.value, miniAppId: account.value.openid });
if (res && res.success) {
await toast('绑定成功');
uni.reLaunch({ url: `/pages/home/home?corpId=${corpId.value}&teamId=${teamId.value}` })
} else {
toast(res?.message || '绑定失败');
}
// customerArchive.value = customers.value.find(item => item.customerId === customerId);
// verifyVisible.value = true;
}
async function init() {
if (customerId.value) {
await getCustomer()
} else {
const res = await getArchives();
if (res.length > 0) {
visible.value = true;
}
}
await getBaseForm();
}
async function getArchives() {
const res = await api('getUnbindMiniAppCustomers', { corpId: corpId.value, mobile: account.value.mobile });
if (res && res.success) {
corpName.value = res.corpName;
customers.value = Array.isArray(res.data) ? res.data : [];
} else {
toast(res?.message || '查询档案信息失败');
return Promise.reject()
}
return customers.value
}
async function getBaseForm() {
const res = await api('getTeamBaseInfo', { corpId: corpId.value, teamId: teamId.value });
if (res && res.success) {
formItems.value = Array.isArray(res.data) ? res.data : [];
} else {
toast(res?.message || '查询失败');
return Promise.reject()
}
}
async function getCustomer() {
const res = await api('getCustomerByCustomerId', { customerId: customerId.value });
console.log(res.data)
if (res && res.success && res.data) {
customer.value = res.data;
} else {
await toast(res?.message || '查询档案信息失败');
uni.navigateBack();
return Promise.reject()
}
}
onLoad(options => {
customerId.value = options.id || '';
uni.setNavigationBarTitle({ title: customerId.value ? '编辑档案' : '新增档案' })
})
useLoad(options => {
teamId.value = options.teamId;
corpId.value = options.corpId;
init();
})
</script>
<style scoped></style>

View File

@ -1,108 +0,0 @@
<template>
<uni-popup ref="popup" type="center" :mask-click="false">
<view class="bg-white rounded overflow-hidden" style="width: 690rpx;">
<view class="flex items-center justify-between px-15 py-12 border-b">
<view class="text-lg font-semibold text-dark">身份校验</view>
<uni-icons type="closeempty" :size="24" color="#999" @click="close"></uni-icons>
</view>
<view class="mt-15 px-15 pt-15 text-base text-dark">
请填写档案人身份证号后四位以确认身份
</view>
<view class="relative flex justify-between mt-15 px-15 py-12 overflow-hidden">
<view v-for="i in 4" :key="i"
class="flex items-center justify-center code-cell text-large font-semibold border-auto text-gray rounded"
:class="i === activeIndex ? 'text-primary' : 'text-gray'">
<text :class="i === activeIndex ? 'text-primary' : 'text-dark'">{{ validCodes[i - 1] || '' }}</text>
</view>
<input class="code-input" type="idcard" :focus="focus" @focus="onFocus" @blur="onBlur" v-model="codes" />
</view>
<view class="footer-buttons">
<button-footer hideden-shadow confirmText="确定" :showCancel="false" @confirm="confirm()" />
</view>
</view>
</uni-popup>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { toast } from '@/utils/widget';
import ButtonFooter from '@/components/button-footer.vue';
const emits = defineEmits(['close', 'confirm'])
const props = defineProps({
corpName: {
type: String,
default: ''
},
customers: {
type: Array,
default: () => []
},
visible: {
type: Boolean,
default: false
}
})
const popup = ref()
const codes = ref('');
const validCodes = computed(() => codes.value.replace(/\s/g, '').split('').slice(0, 4));
const codeStr = computed(() => validCodes.value.join(''));
const activeIndex = computed(() => Math.min(validCodes.value.length + 1, 4))
const focus = ref(false)
const timer = ref(null)
function close() {
emits('close')
}
function confirm() {
if (props.customers.some(i => i._id === id.value && id.value)) {
emits('confirm', id.value)
} else {
toast('请选择档案')
}
}
function onFocus() {
focus.value = true
}
function onBlur() {
focus.value = false
}
watch(() => props.visible, n => {
if (n) {
codes.value = '';
popup.value && popup.value.open();
focus.value = false;
setTimeout(() => focus.value = true, 500)
} else {
popup.value && popup.value.close()
}
})
watch(codes, n => {
if (timer.value) clearTimeout(timer.value);
timer.value = setTimeout(() => {
codes.value = codeStr.value;
}, 500)
})
</script>
<style lang="scss" scoped>
.code-cell {
width: 120rpx;
height: 120rpx;
font-size: 52rpx;
}
.code-input {
position: absolute;
width: 200%;
height: 100%;
top: 0;
left: -100%;
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<full-page :customScroll="articles.length === 0" @reachBottom="loadMore()">
<view v-if="articles.length === 0" class="flex items-center justify-center h-full">
<empty-data />
</view>
<view v-else class="p-15">
<view v-for="article in articles" :key="article._id" class="flex px-15 mb-10 py-12 shadow-lg bg-white rounded">
<image class="flex-shrink-0 mr-10 cover" :src="article.cover || '/static/book.svg'" />
<view class="w-0 flex-grow">
<view class="text-base leading-normal font-semibold truncate mb-5">
{{ article.title }}
</view>
<view v-if="article.summary" class="text-base text-gray line-clamp-2">
{{ article.summary }}
</view>
</view>
</view>
</view>
</full-page>
</template>
<script setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import api from '@/utils/api';
import FullPage from '@/components/full-page.vue';
import EmptyData from '@/components/empty-data.vue';
const corpId = ref('');
const ids = ref('');
const articles = ref([]);
onLoad((options) => {
corpId.value = options.corpId;
ids.value = options.ids;
if (ids.value) {
getArticles()
}
});
async function getArticles() {
const res = await api('getArticleByIds', { corpId: corpId.value, ids: ids.value });
articles.value = res && Array.isArray(res.list) ? res.list : [];
}
function loadMore() {
console.log('addArchive')
}
</script>
<style scoped>
.cover {
width: 128rpx;
height: 128rpx;
}
</style>

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 +0,0 @@
<template>
<full-page :customScroll="empty">
<view v-if="customers.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>
<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>
<view v-else-if="enableHis" class="px-15 py-5 text-sm leading-normal bg-warning text-white rounded-sm">未关联档案
</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>
<view class="text-base leading-normal">证件号{{ customer.idCard || '--' }}</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>
</view>
</view>
<template #footer>
<button-footer confirmText="新增档案" :showCancel="false" @confirm="addArchive()" />
</template>
</full-page>
</template>
<script setup>
import { ref } from 'vue';
import { storeToRefs } from 'pinia'
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';
const empty = ref(false)
const { useLoad, useShow } = useGuard();
const { account } = storeToRefs(useAccount());
const corpId = ref('');
const teamId = ref('');
const enableHis = ref(false);
const customers = ref([]);
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 || '获取档案信息失败')
}
}
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();
} else {
toast(res?.message || '删除失败')
}
}
useLoad(options => {
teamId.value = options.teamId;
corpId.value = options.corpId;
})
useShow(() => {
if (teamId.value && corpId.value) {
getMembers()
}
})
</script>

View File

@ -1,78 +0,0 @@
<template>
<view v-if="articles.length" class="mt-12 px-15 flex items-center justify-between">
<view class="text-lg font-semibold text-dark">健康宣教</view>
<view class="flex items-center" @click="toList()">
<view class="mr-5 text-base text-gray">更多</view>
<uni-icons type="right" color="#999"></uni-icons>
</view>
</view>
<view class="px-15 mt-10">
<view class="shadow-lg bg-white rounded">
<view v-for="article in articles" :key="article._id"
class="flex px-15 py-12 border-b border-solid border-gray-200">
<image class="flex-shrink-0 mr-10 cover" :src="article.cover || '/static/book.svg'" />
<view class="w-0 flex-grow">
<view class="text-base leading-normal font-semibold truncate mb-5">
{{ article.title }}
</view>
<view v-if="article.summary" class="text-base text-gray line-clamp-2">
{{ article.summary }}
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import api from '@/utils/api';
const props = defineProps({
team: {
type: Object,
default: () => ({})
}
})
const articles = ref([])
const qrcode = computed(() => {
const qrcodes = props.team && Array.isArray(props.team.qrcodes) ? props.team.qrcodes : [];
return qrcodes[0] || {}
})
const articleIds = computed(() => {
const articles = qrcode.value && Array.isArray(qrcode.value.articles) ? qrcode.value.articles : [];
const ids = articles.map(item => item._id).filter(i => typeof i === 'string' && i.trim());
return qrcode.value.enableAnnounce === 'YES' ? ids : [];
})
function toList() {
uni.navigateTo({ url: `/pages/article/article-list?corpId=${props.team.corpId}&ids=${articleIds.value.join()}` })
}
async function getArticles() {
const res = await api('getArticleByIds', { corpId: props.team.corpId, ids: articleIds.value.join() });
articles.value = res && Array.isArray(res.list) ? res.list : [];
}
watch(articleIds, n => {
if (n.length) {
getArticles()
} else {
articles.value = []
}
}, { immediate: true })
</script>
<style scoped>
.cover {
width: 128rpx;
height: 128rpx;
}
.min-w-120 {
min-width: 240rpx;
}
.w-80 {
width: 160rpx;
}
</style>

View File

@ -1,170 +0,0 @@
<template>
<view class="px-15 py-12 mb-10 bg-white shadow-lg">
<view class="mb-10 flex items-center justify-between">
<view class="flex-shrink-0 text-lg font-semibold truncate">
成员档案
</view>
<view class="px-10 leading-normal border-dashed-auto text-base text-primary rounded-sm" @click="toManagePage()">
档案管理
</view>
</view>
<view v-if="customers.length === 0" class="flex items-center justify-center h-80 border-dashed text-dark rounded">
<uni-icons type="plusempty" size="16" color="#999"></uni-icons>
<view class="text-base text-dark">新建档案</view>
</view>
<scroll-view scroll-x="true">
<view class="flex flex-nowrap pb-5 ">
<view v-for="i in customers" :key="i._id"
class="flex-shrink-0 min-w-100 mr-10 p-10 rounded relative border-primary"
:class="current && i._id === current._id ? 'bg-primary current-customer' : ''" @click="toggle(i)">
<view class="flex justify-between mb-5">
<view class="text-base leading-normal font-semibold whitespace-nowrap"
:class="current && i._id === current._id ? 'text-white' : 'text-dark'">
{{ i.name }}
</view>
<view v-if="i.relationship" class="flex-shrink-0 px-5 rounded-sm border-auto text-sm leading-normal"
:class="current && i._id === current._id ? 'text-white' : 'text-gray'">
{{ i.relationship }}
</view>
</view>
<view class="text-base leading-normal h-normal"
:class="current && i._id === current._id ? 'text-white' : 'text-gray'">
{{ i.sex }} {{ i.age > 0 ? i.age + '岁' : '' }}
</view>
</view>
</view>
</scroll-view>
<view v-if="canAuth" class="px-10 py-5 mt-5 flex items-center bg-danger rounded-sm">
<view class="mr-5 w-0 flex-grow text-base text-white">
该档案还未授权本服务团队点击右侧授权按钮我们将更精准的为您服务
</view>
<view class="px-12 py-5 text-base rounded-sm text-dark bg-white">
授权
</view>
</view>
<view v-if="current" class="flex mt-10">
<view class="flex-grow p-10 rounded bg-gray mr-10" @click="fillBaseInfo()">
<view class="flex items-center justify-between mb-5">
<view class="text-lg">个人基本信息</view>
<uni-icons color="#999" type="arrowright"></uni-icons>
</view>
<!-- <view v-if="formError.base" class="text-sm text-danger">
请完善您的个人信息 v-else
</view> -->
<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 items-center justify-between mb-5">
<view class="text-lg">个人住院信息</view>
<uni-icons color="#999" type="arrowright"></uni-icons>
</view>
<view class="text-base text-gray">住院信息列表</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'
import useAccount from '@/store/account';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
const props = defineProps({
corpId: {
type: String,
default: ''
},
customers: {
type: Array,
default: () => []
},
team: {
type: Object,
default: () => ({})
}
})
const { account } = storeToRefs(useAccount());
const current = ref(null);
const customers = ref([]);
const canAuth = computed(() => {
if (current.value && props.team && props.team.teamId) {
const teamIds = Array.isArray(current.value.teamId) ? current.value.teamId : [];
return !teamIds.includes(props.team.teamId);
}
return false
})
function fillBaseInfo() {
if (canAuth.value) {
toast('请先授权本服务团队')
} else {
uni.navigateTo({
url: `/pages/archive/edit-archive?teamId=${props.team.teamId}&corpId=${props.corpId}&id=${current.value._id}`,
complete: console.log
})
}
}
function toggle(i) {
current.value = i;
}
function toManagePage() {
uni.navigateTo({ url: `/pages/archive/archive-manage?corpId=${props.corpId}&teamId=${props.team.teamId}` })
}
async function getCustomers() {
const res = await api('getMiniAppCustomers', { miniAppId: account.value.openid, corpId: props.corpId });
if (res && res.success) {
customers.value = res && Array.isArray(res.data) ? res.data : [];
} else {
toast(res.message || '获取档案失败');
}
}
watch(() => props.corpId, n => {
if (n) {
getCustomers()
} else {
customers.value = [];
}
}, { immediate: true });
watch(customers, n => {
if (n.length && !(current.value && n.some(i => i._id === current.value._id))) {
toggle(n[0]);
} else {
current.value = null;
}
})
</script>
<style scoped>
.h-80 {
height: 160rpx;
}
.h-normal {
height: 1.5em;
}
.min-w-100 {
min-width: 200rpx;
}
.current-customer::after {
bottom: -1px;
left: calc(50% - 10px);
border: 10px solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-bottom-color: white;
}
</style>

View File

@ -1,75 +0,0 @@
<template>
<page-loading v-if="loading" />
<full-page v-else-if="teams.length && team">
<template #header>
<team-head :team="team" :teams="teams" @changeTeam="changeTeam" />
<view class="pb-10"></view>
</template>
<customer-archive :corpId="corpId" :team="team" />
<team-mate :team="team" />
<article-list :team="team" />
</full-page>
<yc-home v-else />
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'
import useGuard from '@/hooks/useGuard';
import useAccount from '@/store/account';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
import FullPage from '@/components/full-page.vue';
import articleList from './article-list.vue';
import customerArchive from './customer-archive.vue';
import teamHead from './team-head.vue';
import teamMate from './team-mate.vue';
import ycHome from './yc-home.vue';
import pageLoading from './loading.vue';
const { useLoad, useShow } = useGuard();
const { account } = storeToRefs(useAccount());
const team = ref(null);
const teams = ref([]);
const loading = ref(true)
const corpId = computed(() => team.value?.corpId);
async function changeTeam({ teamId, corpId, corpName }) {
loading.value = true;
const res = await api('getTeamData', { teamId, corpId });
loading.value = false;
if (res && res.data) {
team.value = res.data;
team.value.corpName = corpName;
} else {
toast(res?.message || '获取团队信息失败')
}
}
async function getTeams() {
loading.value = true;
const res = await api('queryWxJoinedTeams', { openid: account.value.openid });
teams.value = res && Array.isArray(res.data) ? res.data : [];
const valid = team.value && teams.value.some(item => item.teamId === team.value.teamId);
if (teams.value.length) {
changeTeam(teams.value[0])
return
} else if (!valid) {
team.value = null;
}
loading.value = false
}
useLoad(opts => {
if (opts.teamId) {
team.value = { teamId: opts.teamId, corpId: opts.corpId };
}
})
useShow(() => {
getTeams();
})
</script>

View File

@ -1,213 +0,0 @@
<template>
<view class="loader-container">
<view class="loader">
<view class="hexagon-container">
<view class="hexagon hex_1"></view>
<view class="hexagon hex_2"></view>
<view class="hexagon hex_3"></view>
<view class="hexagon hex_4"></view>
<view class="hexagon hex_5"></view>
<view class="hexagon hex_6"></view>
<view class="hexagon hex_7"></view>
</view>
</view>
</view>
</template>
<script>
</script>
<style lang="scss" scoped>
.loader-container {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 9999;
background-color: #fefefe;
}
.loader {
position: fixed;
top: 45%;
left: 50%;
width: 80px;
height: 80px;
margin: -40px 0px 0px -40px;
background-color: transparent;
border-radius: 50%;
border: 1px solid rgb(0, 122, 255); //#007aff
// animation: rotate3 3s linear infinite;
&:before {
content: '';
width: 82px;
height: 82px;
display: block;
position: absolute;
border: 1px solid rgba(0, 122, 255, 0.514);
border-radius: 50%;
top: -1px;
left: -1px;
box-sizing: border-box;
// border-bottom-color: transparent;
// border-left-color: transparent;
// border-right-color: transparent;
clip: rect(0px, 17.5px, 17.5px, 0px);
z-index: 10;
animation: rotate infinite;
animation-duration: 3s;
animation-timing-function: linear;
}
&:after {
content: '';
width: 82px;
height: 82px;
display: block;
position: absolute;
border: 1px solid rgba(0, 122, 255, 0.11);
border-radius: 50%;
top: -1px;
left: -1px;
box-sizing: border-box;
// transform: rotate(30deg);
// border-bottom-color: transparent;
// border-left-color: transparent;
// border-right-color: transparent;
clip: rect(0px, 82px, 75px, 0px);
z-index: 9;
// animation: rotate2 infinite, rotate3 infinite;
// animation-duration: 3s;
// animation-timing-function: linner;
animation: rotate2 3s linear infinite;
}
}
.hexagon-container {
position: relative;
top: 16.5px;
left: 20.5px;
border-radius: 50%;
}
.hexagon {
position: absolute;
width: 20px;
height: 11.5px;
background-color: #007aff;
&:before {
content: "";
position: absolute;
top: -5.5px;
left: 0;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 6px solid #007aff;
}
&:after {
content: "";
position: absolute;
top: 11px;
left: 0;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 5.7px solid #007aff;
}
}
$hexagons: (
(1, 0px, 0px),
(2, 0px, 21px),
(3, 18px, 31.5px),
(4, 36px, 21px),
(5, 36px, 0px),
(6, 18px, -10.5px),
(7, 18px, 10.5px)
);
$time: 3s;
$delay: $time / 14;
@each $hexagon in $hexagons {
$index: nth($hexagon, 1);
$top: nth($hexagon, 2);
$left: nth($hexagon, 3);
.hexagon.hex_#{$index} {
top: $top;
left: $left;
animation: Animasearch $time ease-in-out infinite;
animation-delay: $delay * $index;
}
}
@keyframes Animasearch {
0% {
transform: scale(1);
opacity: 1;
}
15%,
50% {
transform: scale(0.5);
opacity: 0;
}
65% {
transform: scale(1);
opacity: 1;
}
}
@keyframes rotate {
0% {
transform: rotate(0);
clip: rect(0px, 17.5px, 17.5px, 0px);
}
50% {
clip: rect(0px, 20px, 20px, 0px);
}
100% {
transform: rotate(360deg);
clip: rect(0px, 17.5px, 17.5px, 0px);
}
}
@keyframes rotate2 {
0% {
transform: rotate(0deg);
clip: rect(0px, 82, 75px, 0px);
}
50% {
clip: rect(0px, 82, 0px, 0px);
transform: rotate(360deg);
}
100% {
transform: rotate(720deg);
clip: rect(0px, 164px, 75px, 0px);
}
}
@keyframes rotate3 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,123 +0,0 @@
<template>
<view>
<view :style="{ height: statusBarHeight }" class="bg-primary"></view>
<view class="relative z-3 flex items-center px-15 py-12 bg-primary">
<view class="flex-shrink-0 mr-5">
<group-avatar :size="120" :avatarList="currentTeam ? currentTeam.avatarList : []" />
</view>
<view class="w-0 flex-grow ">
<view class="flex mb-10">
<view class="w-0 flex-grow truncate text-lg font-semibold text-white">{{ team.name }}</view>
<view v-if="teams.length > 1" class="flex-shinrk-0 flex items-center px-10 bg-white rounded-sm"
@click="showDropDown = true">
<view class="text-base">切换</view>
<uni-icons type="down" size="12"></uni-icons>
</view>
</view>
<view v-if="currentTeam" class="text-base text-white truncate">{{ currentTeam.corpName }}</view>
</view>
<view v-if="menuButtonInfo && menuButtonInfo.width > 0" class="flex-shrink-0"
:style="{ width: menuButtonInfo.width + 'px', height: menuButtonInfo.height + 'px' }">
</view>
</view>
<view class="relative">
<view v-if="showDropDown" class="team-dropdown py-12 bg-white shadow-lg">
<scroll-view scroll-y="true" style="max-height: 50vh;">
<view class="px-15">
<view v-for="item in teams" :key="item.teamId" class="mb-10 p-10 flex items-center bg-gray rounded-sm">
<view class="flex-shrink-0 mr-5">
<group-avatar :size="96" :avatarList="item.avatarList" />
</view>
<view class="w-0 flex-grow mr-5">
<view class="mb-5 text-lg font-semibold text-dark">{{ item.name }}</view>
<view class="text-base text-gray leading-normal">{{ item.corpName }}</view>
</view>
<view class="flex">
<image class="check-icon"
:src="team && team.teamId === item.teamId ? '/static/form/checked.svg' : '/static/form/unchecked.svg'">
</image>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view v-if="team.teamTroduce" class="px-15 py-12 flex bg-white border-b shadow-lg">
<image class="laba-icon flex-shrink-0 mr-5" src="/static/laba.svg"></image>
<view class="w-0 flex-grow text-sm text-gray leading-normal line-clamp-2">{{ team.teamTroduce }} </view>
</view>
</view>
<view v-if="showDropDown" class="mask" @click="showDropDown = false"></view>
</template>
<script setup>
import { computed, ref, onMounted, watch } from 'vue';
import groupAvatar from '@/components/group-avatar.vue';
const statusBarHeight = ref('50px');
const menuButtonInfo = ref(null);
const showDropDown = ref(false)
const emits = defineEmits(['changeTeam']);
const props = defineProps({
team: {
type: Object,
default: () => ({})
},
teams: {
type: Array,
default: () => []
}
})
const currentTeam = computed(() => props.teams.find(i => props.team && i.teamId === props.team.teamId))
watch(() => props.teams, (teams) => {
if (teams.length && !(currentTeam.value && teams.some(i => i.teamId === currentTeam.value.teamId))) {
emits('changeTeam', teams[0])
}
})
onMounted(() => {
const win = uni.getWindowInfo();
if (win && win.statusBarHeight > 0) {
statusBarHeight.value = win.statusBarHeight + 'px';
}
menuButtonInfo.value = uni.getMenuButtonBoundingClientRect();
})
</script>
<style scoped>
.laba-icon {
width: 36rpx;
height: 36rpx;
}
.check-icon {
width: 40rpx;
height: 40rpx;
}
.mask {
position: fixed;
z-index: 2;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
}
.z-3 {
z-index: 3;
}
.team-dropdown {
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 3;
border-bottom-left-radius: 16rpx;
border-bottom-right-radius: 16rpx;
}
</style>

View File

@ -1,75 +0,0 @@
<template>
<view class="mt-12 px-15 flex items-center justify-between">
<view class="text-lg font-semibold text-dark">团队成员</view>
<view class="flex items-center" @click="toTeamDetail()">
<view class="mr-5 text-base text-gray">团队详情</view>
<uni-icons type="right" color="#999"></uni-icons>
</view>
</view>
<view class="px-15 mt-10">
<scroll-view scroll-x="true">
<view class="flex flex-nowrap pb-5 border-b">
<view v-for="i in teamates" :key="i.userid"
class="flex flex-shrink-0 min-w-120 p-10 mr-10 rounded-sm border-auto text-primary bg-white"
@click="toHomePage(i)">
<image class="flex-shrink-0 avatar mr-5" :src="i.avatar || '/static/default-avatar.png'" />
<view class="flex-grow flex flex-col">
<view class="text-lg font-semibold text-dark whitespace-nowrap">
{{ i.anotherName }}
</view>
<view class="text-base text-gray truncate">
医生
</view>
<view v-if="i.canAddFriend" class="w-80 text-base leading-none border text-center text-dark rounded-full"
@click.stop="toQrcode(i)">
添加好友
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
team: {
type: Object,
default: () => ({})
}
})
const teamates = computed(() => {
const friendlyMembers = props.team && Array.isArray(props.team.friendlyMembers) ? props.team.friendlyMembers : [];
const memberList = props.team && Array.isArray(props.team.memberList) ? props.team.memberList : [];
return memberList.map(i => ({ ...i, canAddFriend: friendlyMembers.includes(i.userid) }))
})
function toHomePage(item) {
uni.navigateTo({ url: `/pages/team/homepage?userid=${item.userid}&corpId=${item.corpId}` })
}
function toQrcode(item) {
uni.navigateTo({ url: `/pages/team/friend?userid=${item.userid}&corpId=${item.corpId}` })
}
function toTeamDetail() {
uni.navigateTo({ url: `/pages/team/team-detail?teamId=${props.team.teamId}&corpId=${props.team.corpId}&corpName=${encodeURIComponent(props.team.corpName)}` })
}
</script>
<style scoped>
.avatar {
width: 120rpx;
height: 128rpx;
}
.min-w-120 {
min-width: 240rpx;
}
.w-80 {
width: 160rpx;
}
</style>

View File

@ -1,45 +0,0 @@
<template>
<view class="h-full flex flex-col">
<view class="flex-shrink-0 w-full">
<view :style="{ height: statusBarHeight }" class="bg-primary"></view>
<view class="relative z-3 flex items-center px-15 py-12 bg-primary">
<view class="flex-shrink-0 mr-10">
<image class="logo" src="/static/logo-plain.png"></image>
</view>
<view class="w-0 flex-grow">
<view class="text-lg font-semibold text-white">柚健康 </view>
<view class="leading-normal text-base text-white truncate">生命全周期健康管理伙伴</view>
</view>
<view v-if="menuButtonInfo && menuButtonInfo.width > 0" class="flex-shrink-0"
:style="{ width: menuButtonInfo.width + 'px', height: menuButtonInfo.height + 'px' }">
</view>
</view>
</view>
<view class="flex-grow flex flex-col items-center justify-center bg-white">
<empty-data :showText="false" />
<view class="mb-10 text-lg text-dark font-semibold">暂无团队</view>
<view class="text-lg text-dark font-semibold">需要扫团队二维码绑定服务团队哦</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import emptyData from '@/components/empty-data.vue';
const statusBarHeight = ref('50px');
const menuButtonInfo = ref(null);
onMounted(() => {
const win = uni.getWindowInfo();
if (win && win.statusBarHeight > 0) {
statusBarHeight.value = win.statusBarHeight + 'px';
}
menuButtonInfo.value = uni.getMenuButtonBoundingClientRect();
})
</script>
<style scoped>
.logo {
width: 120rpx;
height: 120rpx;
}
</style>

View File

@ -1,9 +1,13 @@
<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-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 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>
@ -11,18 +15,27 @@
<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
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-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="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>
@ -30,17 +43,17 @@
</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) {
@ -48,9 +61,9 @@ function attempRedirect(url) {
uni.redirectTo({
url,
success: () => resolve(true),
fail: () => reject(false)
})
})
fail: () => reject(false),
});
});
}
function attempSwitchTab(url) {
@ -58,19 +71,19 @@ function attempSwitchTab(url) {
uni.switchTab({
url,
success: () => resolve(true),
fail: () => reject(false)
})
})
fail: () => reject(false),
});
});
}
function remind() {
toast('请先阅读并同意用户协议和隐私政策');
toast("请先阅读并同意用户协议和隐私政策");
}
function toHome() {
uni.navigateTo({
url: '/pages/home/home'
})
url: "/pages/home/home",
});
}
async function getPhoneNumber(e) {
@ -78,9 +91,9 @@ async function getPhoneNumber(e) {
if (e && !phoneCode) return;
const res = await login(phoneCode);
if (res && redirectUrl.value) {
await attempToPage(redirectUrl.value)
await attempToPage(redirectUrl.value);
} else if (res) {
toHome()
toHome();
}
}
@ -89,18 +102,18 @@ async function attempToPage(url) {
if (res1) return;
const res2 = attempSwitchTab(url);
if (res2) return;
toHome()
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
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 || '';
})
redirectUrl.value = opts.redirectUrl || "";
});
</script>
<style scoped>
.pt-lg {

View File

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

View File

@ -1,93 +0,0 @@
<template>
<view v-if="member" class="flex flex-col h-full items-center justify-center">
<view class="business-card">
<view class="flex">
<image class="mr-10 avatar" :src="member.avatar || '/static/default-avatar.png'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center">
<view class="mr-5 text-lg font-semibold text-dark">{{ member.anotherName }}</view>
<view class="text-base text-warning">@企业微信</view>
</view>
<view class="text-base text-dark">咨询师</view>
</view>
</view>
<view class="mt-12 border-primary qrcode p-15 mx-auto rounded" @click="previewImage()">
<image v-if="qrcode" class="h-full w-full" :src="qrcode"></image>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
const corpId = ref('');
const userid = ref('');
const qrcode = ref('')
const member = ref(null);
const corpNames = computed(() => {
const corpNames = member.value && Array.isArray(member.value.corpNames) ? member.value.corpNames : [];
return corpNames.join('、');
})
const deptNames = computed(() => {
const deptNames = member.value && Array.isArray(member.value.deptNames) ? member.value.deptNames : [];
return deptNames.join('、');
})
function previewImage() {
if (!qrcode.value) return;
uni.previewImage({
urls: [qrcode.value]
})
}
async function getMember() {
const res = await api('getCorpMemberHomepageInfo', { userid: userid.value, corpId: corpId.value });
if (res && res.success) {
member.value = res.data;
if (!qrcode.value) {
getQrcode();
}
} else {
toast(res.message || '获取医生信息失败')
}
}
async function getQrcode() {
const res = await api('addContactWay', { corpUserId: userid.value, corpId: corpId.value });
if (res && res.data) {
qrcode.value = res.data;
}
}
onLoad((options) => {
corpId.value = options.corpId;
userid.value = options.userid;
});
onShow(() => {
if (corpId.value && userid.value) {
getMember()
}
})
</script>
<style scoped>
.business-card {
width: 600rpx;
}
.avatar {
width: 80rpx;
height: 96rpx;
}
.qrcode {
width: 560rpx;
height: 560rpx;
}
</style>

View File

@ -1,159 +0,0 @@
<template>
<view v-if="member" class="flex p-15 bg-whtie shadow-lg">
<view class="flex-grow w-0 mr-10 leading-normal">
<view>
<text class="mr-5 text-xl text-dark font-semibold">{{ member.anotherName }}</text>
<text class="text-base text-gray">医生</text>
</view>
<view class="flex">
<view class="flex-shrink-0 text-base text-gray">机构部门</view>
<view class="flex-shrink-0 text-base text-dark">{{ deptNames }}</view>
</view>
<view class="flex">
<view class="flex-shrink-0 text-base text-gray">执业机构</view>
<view class="flex-shrink-0 text-base text-dark">{{ corpNames }}</view>
</view>
</view>
<image class="avatar" :src="member.avatar"></image>
</view>
<view v-if="member" class="p-15 mt-12 leading-normal bg-white shadow-lg">
<view class="flex items-center" @click="expand = !expand">
<image class="flex-shrink-0 mr-10 section-icon" src="https://picsum.photos/300/300"></image>
<view class="w-0 flex-grow text-lg font-semibold">个人简介</view>
<uni-icons v-if="member.memberTroduce" :type="expand ? 'up' : 'down'" size="16"></uni-icons>
</view>
<view class="mt-10 text-dark text-base" :class="expand ? '' : 'line-clamp-4'">
{{ member.memberTroduce || '暂无简介' }}
</view>
<view class="mt-20 flex items-center">
<image class="flex-shrink-0 mr-10 section-icon" src="https://picsum.photos/300/300"></image>
<view class="w-0 flex-grow text-lg font-semibold">门诊时间</view>
</view>
<view class="mt-10 text-dark text-base">
{{ member.outpatientTime || '暂无门诊时间' }}
</view>
<view class="mt-20 flex items-center">
<image class="flex-shrink-0 mr-10 section-icon" src="https://picsum.photos/300/300"></image>
<view class="w-0 flex-grow text-lg font-semibold">对外联系电话</view>
</view>
<view class="mt-10 text-dark" :class="member.callNumber ? 'text-primary' : 'text-gray'" @click="callNumber()">
{{ member.callNumber || '暂无联系电话' }}
</view>
<view class="mt-20 flex items-center">
<image class="flex-shrink-0 mr-10 section-icon" src="https://picsum.photos/300/300"></image>
<view class="w-0 flex-grow text-lg font-semibold">便民服务</view>
</view>
<view class="mt-10 flex">
<view class="px-15 py-5 text-base text-white bg-primary rounded-sm">预约挂号</view>
<view class="px-15 py-5 ml-15 text-base text-white bg-primary rounded-sm">在线咨询</view>
</view>
</view>
<view v-if="qrcode" class="p-15 mt-12 leading-normal bg-white shadow-lg">
<view class="text-lg font-semibold text-center text-dark">
点击下方二维码加我为好友
</view>
<view class="mt-12 border-primary qrcode p-15 mx-auto rounded" @click="previewImage()">
<image :src="qrcode" class="h-full w-full"></image>
</view>
</view>
<view class="safe-bottom-padding"></view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
const corpId = ref('');
const userid = ref('');
const showQrcode = ref(false);
const qrcode = ref('')
const member = ref(null);
const expand = ref(false);
const corpNames = computed(() => {
const corpNames = member.value && Array.isArray(member.value.corpNames) ? member.value.corpNames : [];
return corpNames.join('、');
})
const deptNames = computed(() => {
const deptNames = member.value && Array.isArray(member.value.deptNames) ? member.value.deptNames : [];
return deptNames.join('、');
})
function callNumber() {
if (member.value && member.value.callNumber) {
uni.makePhoneCall({
phoneNumber: member.value.callNumber
})
}
}
function previewImage() {
uni.previewImage({
urls: [qrcode.value]
})
}
async function getMember() {
const res = await api('getCorpMemberHomepageInfo', { userid: userid.value, corpId: corpId.value });
if (res && res.success) {
member.value = res.data;
if ( showQrcode.value && !qrcode.value) {
getQrcode();
}
} else {
toast(res.message || '获取医生信息失败')
}
}
async function getQrcode() {
const res = await api('addContactWay', { corpUserId: userid.value, corpId: corpId.value });
if (res && res.data ) {
qrcode.value = res.data;
}
}
onLoad((options) => {
corpId.value = options.corpId;
userid.value = options.userid;
showQrcode.value = options.showQrcode;
});
onShow(() => {
if (corpId.value && userid.value) {
getMember()
}
})
</script>
<style>
page {
overflow: auto;
}
.avatar {
width: 120rpx;
height: 128rpx;
}
.section-icon {
width: 48rpx;
height: 48rpx;
}
.mt-20 {
margin-top: 40rpx;
}
.line-clamp-4 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.qrcode {
width: 560rpx;
height: 560rpx;
}
</style>

View File

@ -1,150 +0,0 @@
<template>
<view v-if="team" class="p-15">
<view class="flex items-center">
<view class="flex-shrink-0 mr-10">
<group-avatar :size="96" :avatarList="avatarList" />
</view>
<view class="flex-grow w-0 leading-noraml">
<view class="mb-5 text-lg font-semibold text-dark">{{ team.name }}</view>
<view class="text-base text-gray">
{{ corpName }}
</view>
</view>
</view>
<view v-if="team.teamTroduce" class="mt-12 text-base text-dark leading-normal break-all">
{{ team.teamTroduce }}
</view>
<template v-if="teammate.leaders.length">
<view class="min-w-100 inline-block mt-12 px-10 py-5 text-center text-base text-white bg-primary rounded-sm">
团队负责人
</view>
<view v-for="i in teammate.leaders" :key="i._id" class="mt-12 flex p-10 border-primary rounded-sm"
@click="toHomePage(i.userid)">
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.png'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center justify-between">
<view class="flex-grow w-0">
<text class="mr-5 text-lg text-dark font-semibold">{{ i.anotherName }}</text>
<text class="text-base text-dark">医生</text>
</view>
<view v-if="friendlyMember[i.userid]"
class="px-10 leading-normal text-sm border-auto text-primary rounded-full"
@click.stop="toFriend(i.userid)">
添加好友
</view>
</view>
<view class="line-clamp-2 text-base text-gray">
{{ i.memberTroduce || '暂无简介' }}
</view>
</view>
</view>
</template>
<template v-if="teammate.members.length">
<view class="min-w-100 inline-block mt-12 px-10 py-5 text-center text-base text-white bg-primary rounded-sm">团队成员
</view>
<view v-for="i in teammate.members" :key="i._id" class="mt-12 flex p-10 border-primary rounded-sm"
@click="toHomePage(i.userid)">
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.png'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center justify-between">
<view class="flex-grow w-0">
<text class="mr-5 text-lg text-dark font-semibold">{{ i.anotherName }}</text>
<text class="text-base text-dark">医生</text>
</view>
<view v-if="friendlyMember[i.userid]"
class="px-10 leading-normal text-sm border-auto text-primary rounded-full"
@click.stop="toFriend(i.userid)">
添加好友
</view>
</view>
<view class="line-clamp-2 text-base text-gray">
{{ i.memberTroduce || '暂无简介' }}
</view>
</view>
</view>
</template>
<view class="safe-bottom-padding"></view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import api from '@/utils/api';
import groupAvatar from '@/components/group-avatar.vue';
const corpId = ref('');
const teamId = ref('');
const team = ref(null);
const corpName = ref('');
const memberList = computed(() => team.value && Array.isArray(team.value.memberList) ? team.value.memberList : [])
const avatarList = computed(() => memberList.value.map(i => i.avatar || '/static/default-avatar.png').filter(Boolean))
const teammate = computed(() => {
const memberLeaderList = team.value && Array.isArray(team.value.memberLeaderList) ? team.value.memberLeaderList : [];
return memberList.value.reduce((data, item) => {
if (memberLeaderList.includes(item.userid)) {
data.leaders.push(item)
} else {
data.members.push(item)
}
return data
}, { leaders: [], members: [] })
})
const friendlyMember = computed(() => {
const friendlyMembers = team.value && Array.isArray(team.value.friendlyMembers) ? team.value.friendlyMembers : [];
return friendlyMembers.reduce((data, item) => {
data[item] = true;
return data
}, {})
})
function toFriend(userid) {
uni.navigateTo({ url: `/pages/team/friend?corpId=${corpId.value}&userid=${userid}` })
}
function toHomePage(userid) {
uni.navigateTo({ url: `/pages/team/homepage?corpId=${corpId.value}&userid=${userid}&showQrcode=${friendlyMember[userid] ? 'YES' : ''}` })
}
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 || '获取团队信息失败')
}
}
onLoad(options => {
corpId.value = options.corpId;
teamId.value = options.teamId;
corpName.value = decodeURIComponent(options.corpName || '');
})
onShow(() => {
if (teamId.value && corpId.value) {
getTeam()
}
});
</script>
<style>
page {
background: white;
overflow: auto;
}
.min-w-100 {
min-width: 200rpx;
}
.avatar {
width: 120rpx;
height: 128rpx;
}
</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

@ -3,42 +3,6 @@ export default [
path: 'pages/home/home',
meta: { title: '首页', login: true },
style: { navigationStyle: 'custom' }
},
{
path: 'pages/login/login',
meta: { title: '柚健康' },
},
{
path: 'pages/login/redirect-page',
meta: { title: '柚健康' },
},
{
path: 'pages/archive/archive-manage',
meta: { title: '档案管理', login: true }
},
{
path: 'pages/archive/edit-archive',
meta: { title: '新增档案', login: true }
},
{
path: 'pages/article/article-list',
meta: { title: '健康宣教', login: true }
},
{
path: 'pages/health/list',
meta: { title: '健康信息', login: true }
},
{
path: 'pages/team/team-detail',
meta: { title: '团队介绍', login: true }
},
{
path: 'pages/team/homepage',
meta: { title: '个人主页', login: true }
},
{
path: 'pages/team/friend',
meta: { title: '添加好友', login: true }
}
]

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