@ -0,0 +1,8 @@
|
|||||||
|
# H5应用端口
|
||||||
|
VITE_APP_PORT = 3000
|
||||||
|
|
||||||
|
# H5代理前缀
|
||||||
|
VITE_APP_PROXY_PREFIX = "/dev-api"
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
|
VITE_APP_BASE_URL = "http://localhost:8080"
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
# 接口地址
|
||||||
|
VITE_APP_BASE_URL = "http://prod-api"
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
.hbuilderx
|
||||||
|
.project
|
||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
unpackage
|
||||||
|
package-lock.json
|
||||||
|
pnpm-lock.yaml
|
||||||
@ -0,0 +1 @@
|
|||||||
|
npx --no-install commitlint --edit $1
|
||||||
@ -0,0 +1 @@
|
|||||||
|
npm run lint:lint-staged
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
"*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}": ["prettier --write"],
|
||||||
|
};
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
unpackage
|
||||||
|
node_modules
|
||||||
|
uni_modules
|
||||||
|
static
|
||||||
|
.husky
|
||||||
|
.hbuilderx
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.sh
|
||||||
|
*.md
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
onLaunch,
|
||||||
|
onShow,
|
||||||
|
onHide,
|
||||||
|
onError,
|
||||||
|
onPageNotFound,
|
||||||
|
} from "@dcloudio/uni-app";
|
||||||
|
import { checkForUpdate } from "@/utils";
|
||||||
|
|
||||||
|
onLaunch(() => {
|
||||||
|
console.log("App Launch");
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
checkForUpdate();
|
||||||
|
// #endif
|
||||||
|
});
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
console.log("App Show");
|
||||||
|
});
|
||||||
|
|
||||||
|
onHide(() => {
|
||||||
|
console.log("App Hide");
|
||||||
|
});
|
||||||
|
|
||||||
|
onError((error) => {
|
||||||
|
console.error("App Error", error);
|
||||||
|
});
|
||||||
|
|
||||||
|
onPageNotFound((res) => {
|
||||||
|
console.error("PageNotFound", res);
|
||||||
|
uni.redirectTo({
|
||||||
|
url: "/pages/404/404",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
/* 每个页面公共css */
|
||||||
|
page {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* uv-ui基础样式 */
|
||||||
|
@import "@/uni_modules/uv-ui-tools/index.scss";
|
||||||
|
</style>
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 白開水
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
import AuthAPI from "./modules/auth";
|
||||||
|
import UserAPI from "./modules/user";
|
||||||
|
|
||||||
|
export { AuthAPI, UserAPI };
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
import http from "@/utils/request";
|
||||||
|
|
||||||
|
class AuthAPI {
|
||||||
|
// 注册
|
||||||
|
static signUp(data) {
|
||||||
|
return http.post("/auth/signup", data, {
|
||||||
|
custom: {
|
||||||
|
loading: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
static signIn(data) {
|
||||||
|
return http.post("/auth/signin", data, {
|
||||||
|
custom: {
|
||||||
|
loading: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新token
|
||||||
|
static refreshToken(header = {}) {
|
||||||
|
return http.post("/auth/refresh", undefined, {
|
||||||
|
header,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AuthAPI;
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import http from "@/utils/request";
|
||||||
|
|
||||||
|
class UserAPI {
|
||||||
|
// test get api
|
||||||
|
static getUserList(params = {}) {
|
||||||
|
return http.get("/user/list", {
|
||||||
|
params,
|
||||||
|
custom: {
|
||||||
|
auth: true,
|
||||||
|
loading: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserAPI;
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<text
|
||||||
|
:class="`iconfont icon-${name}`"
|
||||||
|
:style="{
|
||||||
|
color: color,
|
||||||
|
'font-size': size + 'px',
|
||||||
|
}"
|
||||||
|
@click="handleClick"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const emit = defineEmits(["click"]);
|
||||||
|
const props = defineProps({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: "#333333",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 16,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
emit("click");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "./iconfont.css";
|
||||||
|
</style>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "iconfont"; /* Project id 4657887 */
|
||||||
|
src:
|
||||||
|
url("iconfont.woff2?t=1724050101808") format("woff2"),
|
||||||
|
url("iconfont.woff?t=1724050101808") format("woff"),
|
||||||
|
url("iconfont.ttf?t=1724050101808") format("truetype");
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-uniapp:before {
|
||||||
|
content: "\e624";
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"id": "4657887",
|
||||||
|
"name": "vue3-uniapp-template",
|
||||||
|
"font_family": "iconfont",
|
||||||
|
"css_prefix_text": "icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "19317486",
|
||||||
|
"name": "uniapp",
|
||||||
|
"font_class": "uniapp",
|
||||||
|
"unicode": "e624",
|
||||||
|
"unicode_decimal": 58916
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<picker
|
||||||
|
range-key="label"
|
||||||
|
:range="langOptions"
|
||||||
|
:value="langIndex"
|
||||||
|
@change="handleLangChange"
|
||||||
|
>
|
||||||
|
<slot>
|
||||||
|
<image
|
||||||
|
:style="langStyle"
|
||||||
|
src="data:image/png;base64,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"
|
||||||
|
></image>
|
||||||
|
</slot>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const emit = defineEmits(["change"]);
|
||||||
|
const props = defineProps({
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 40,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { locale, t } = useI18n();
|
||||||
|
const langStyle = {
|
||||||
|
width: props.size + "rpx",
|
||||||
|
height: props.size + "rpx",
|
||||||
|
};
|
||||||
|
const langOptions = computed(() => {
|
||||||
|
return [
|
||||||
|
{ label: t("locale.en"), value: "en" },
|
||||||
|
{ label: t("locale.zh-hans"), value: "zh-Hans" },
|
||||||
|
{ label: t("locale.zh-hant"), value: "zh-Hant" },
|
||||||
|
{ label: t("locale.ja"), value: "ja" },
|
||||||
|
];
|
||||||
|
});
|
||||||
|
const langIndex = computed(() => {
|
||||||
|
return langOptions.value.findIndex((item) => {
|
||||||
|
return item.value === locale.value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
function handleLangChange(event) {
|
||||||
|
const lang = langOptions.value[event.detail.value].value;
|
||||||
|
locale.value = lang;
|
||||||
|
uni.setLocale(lang);
|
||||||
|
emit("change", lang);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { hasPerm } from "@/plugins/permission";
|
||||||
|
import { currentRoute } from "@/router";
|
||||||
|
|
||||||
|
// 对某些特殊场景需要在页面onShow生命周期中校验权限:
|
||||||
|
// 1.微信小程序端点击tabbar的底层逻辑不触发uni.switchTab
|
||||||
|
// 2.h5在浏览器地址栏输入url后跳转不触发uni的路由api
|
||||||
|
// 3.首次启动加载的页面不触发uni的路由api
|
||||||
|
export async function usePermission() {
|
||||||
|
return hasPerm(currentRoute());
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport =
|
||||||
|
"CSS" in window &&
|
||||||
|
typeof CSS.supports === "function" &&
|
||||||
|
(CSS.supports("top: env(a)") || CSS.supports("top: constant(a)"));
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ", viewport-fit=cover" : "") +
|
||||||
|
'" />'
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"locale.auto": "System",
|
||||||
|
"locale.en": "English",
|
||||||
|
"locale.zh-hans": "Simplified Chinese",
|
||||||
|
"locale.zh-hant": "Traditional Chinese",
|
||||||
|
"locale.ja": "Japanese",
|
||||||
|
"index.demo": "uni-app internationalization demo"
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { createI18n } from "vue-i18n"; // v9.x
|
||||||
|
import en from "./en.json";
|
||||||
|
import ja from "./ja.json";
|
||||||
|
import zhHans from "./zh-Hans.json";
|
||||||
|
import zhHant from "./zh-Hant.json";
|
||||||
|
|
||||||
|
const i18n = createI18n({
|
||||||
|
legacy: false, // 必须设置false才能使用Composition API
|
||||||
|
globalInjection: true, // 为每个组件注入$为前缀的全局属性和函数
|
||||||
|
locale: uni.getLocale(),
|
||||||
|
messages: {
|
||||||
|
en,
|
||||||
|
"zh-Hans": zhHans,
|
||||||
|
"zh-Hant": zhHant,
|
||||||
|
ja,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function setupI18n(app) {
|
||||||
|
app.use(i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { i18n };
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"locale.auto": "システム",
|
||||||
|
"locale.en": "英語",
|
||||||
|
"locale.zh-hans": "簡体字中国語",
|
||||||
|
"locale.zh-hant": "繁体字中国語",
|
||||||
|
"locale.ja": "日本語",
|
||||||
|
"index.demo": "uni-app 国際化デモ"
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"common": {
|
||||||
|
"uni.app.quit": "もう一度押すと、アプリケーションが終了します",
|
||||||
|
"uni.async.error": "サーバーへの接続がタイムアウトしました。画面をクリックして再試行してください",
|
||||||
|
"uni.showActionSheet.cancel": "キャンセル",
|
||||||
|
"uni.showToast.unpaired": "使用するには、showToastとhideToastをペアにする必要があることに注意してください",
|
||||||
|
"uni.showLoading.unpaired": "使用するには、showLoadingとhideLoadingをペアにする必要があることに注意してください",
|
||||||
|
"uni.showModal.cancel": "キャンセル",
|
||||||
|
"uni.showModal.confirm": "OK",
|
||||||
|
"uni.chooseImage.cancel": "キャンセル",
|
||||||
|
"uni.chooseImage.sourceType.album": "アルバムから選択",
|
||||||
|
"uni.chooseImage.sourceType.camera": "カメラ",
|
||||||
|
"uni.chooseVideo.cancel": "キャンセル",
|
||||||
|
"uni.chooseVideo.sourceType.album": "アルバムから選択",
|
||||||
|
"uni.chooseVideo.sourceType.camera": "カメラ",
|
||||||
|
"uni.previewImage.cancel": "キャンセル",
|
||||||
|
"uni.previewImage.button.save": "画像を保存",
|
||||||
|
"uni.previewImage.save.success": "画像をアルバムに正常に保存します",
|
||||||
|
"uni.previewImage.save.fail": "画像をアルバムに保存できませんでした",
|
||||||
|
"uni.setClipboardData.success": "コンテンツがコピーされました",
|
||||||
|
"uni.scanCode.title": "スキャンコード",
|
||||||
|
"uni.scanCode.album": "アルバム",
|
||||||
|
"uni.scanCode.fail": "認識に失敗しました",
|
||||||
|
"uni.scanCode.flash.on": "タッチして点灯",
|
||||||
|
"uni.scanCode.flash.off": "タップして閉じる",
|
||||||
|
"uni.startSoterAuthentication.authContent": "指紋認識...",
|
||||||
|
"uni.picker.done": "完了",
|
||||||
|
"uni.picker.cancel": "キャンセル",
|
||||||
|
"uni.video.danmu": "「弾幕」",
|
||||||
|
"uni.video.volume": "ボリューム",
|
||||||
|
"uni.button.feedback.title": "質問のフィードバック",
|
||||||
|
"uni.button.feedback.send": "送信"
|
||||||
|
},
|
||||||
|
"ios": {},
|
||||||
|
"android": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"locale.auto": "系统",
|
||||||
|
"locale.en": "英语",
|
||||||
|
"locale.zh-hans": "简体中文",
|
||||||
|
"locale.zh-hant": "繁体中文",
|
||||||
|
"locale.ja": "日语",
|
||||||
|
"index.demo": "uni-app 国际化演示"
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"locale.auto": "系統",
|
||||||
|
"locale.en": "英語",
|
||||||
|
"locale.zh-hans": "簡體中文",
|
||||||
|
"locale.zh-hant": "繁體中文",
|
||||||
|
"locale.ja": "日語",
|
||||||
|
"index.demo": "uni-app 國際化演示"
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import App from "./App";
|
||||||
|
import { createSSRApp } from "vue";
|
||||||
|
import setupPlugins from "@/plugins";
|
||||||
|
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App);
|
||||||
|
app.use(setupPlugins);
|
||||||
|
return {
|
||||||
|
app,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"name" : "卡叔电梯",
|
||||||
|
"appid" : "__UNI__3A16C1C",
|
||||||
|
"description" : "",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
/* 5+App特有相关 */
|
||||||
|
"app-plus" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"compilerVersion" : 3,
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
/* 模块配置 */
|
||||||
|
"modules" : {},
|
||||||
|
/* 应用发布信息 */
|
||||||
|
"distribute" : {
|
||||||
|
/* android打包配置 */
|
||||||
|
"android" : {
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
|
],
|
||||||
|
"minSdkVersion" : 21
|
||||||
|
},
|
||||||
|
/* ios打包配置 */
|
||||||
|
"ios" : {},
|
||||||
|
/* SDK配置 */
|
||||||
|
"sdkConfigs" : {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 快应用特有相关 */
|
||||||
|
"quickapp" : {},
|
||||||
|
/* 小程序特有相关 */
|
||||||
|
"mp-weixin" : {
|
||||||
|
"appid" : "wx2c04ebae2099b3d2",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false,
|
||||||
|
"es6" : true,
|
||||||
|
"postcss" : true,
|
||||||
|
"minified" : true
|
||||||
|
},
|
||||||
|
"usingComponents" : true,
|
||||||
|
"permission" : {
|
||||||
|
"scope.userLocation" : {
|
||||||
|
"desc" : "获取当前位置"
|
||||||
|
},
|
||||||
|
"scope.userFuzzyLocation" : {
|
||||||
|
"desc" : "您的位置信息将用于小程序位置接口的效果展示"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 地理位置相关接口配置项 @see https://developers.weixin.qq.com/community/develop/doc/000a02f2c5026891650e7f40351c01 */
|
||||||
|
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ]
|
||||||
|
},
|
||||||
|
"mp-alipay" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-baidu" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-toutiao" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : false
|
||||||
|
},
|
||||||
|
"vueVersion" : "3",
|
||||||
|
"h5" : {
|
||||||
|
"optimization" : {
|
||||||
|
"treeShaking" : {
|
||||||
|
"enable" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devServer" : {
|
||||||
|
"https" : false
|
||||||
|
},
|
||||||
|
"router" : {
|
||||||
|
"mode" : "history"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locale" : "auto"
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "lift-wechat",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "卡叔电梯",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"prepare": "husky",
|
||||||
|
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"",
|
||||||
|
"lint:lint-staged": "lint-staged",
|
||||||
|
"commit": "git-cz"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"卡叔电梯"
|
||||||
|
],
|
||||||
|
"author": "Lufaneng",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"dayjs": "^1.11.18",
|
||||||
|
"three": "^0.178.0",
|
||||||
|
"vue-draggable-plus": "^0.6.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^19.1.0",
|
||||||
|
"@commitlint/config-conventional": "^19.1.0",
|
||||||
|
"@dcloudio/types": "^3.4.11",
|
||||||
|
"commitizen": "^4.3.0",
|
||||||
|
"cz-git": "^1.9.0",
|
||||||
|
"husky": "^9.0.11",
|
||||||
|
"lint-staged": "^15.2.2",
|
||||||
|
"prettier": "^3.2.5"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "node_modules/cz-git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<HeaderCustom title="我的"></HeaderCustom>
|
||||||
|
<div class="titleBox">
|
||||||
|
<div class="avatar">
|
||||||
|
<img class="img" src="/static/imgs/avatar.png" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="name" v-if="authStore?.isLoggedIn">{{userStore.userInfo.nickname}}</div>
|
||||||
|
<div class="name" v-else @click="handleLogin">登录/注册</div>
|
||||||
|
</div>
|
||||||
|
<div class="cellBox">
|
||||||
|
<uv-cell-group :customStyle="{backgroundColor:'#fff'}">
|
||||||
|
<uv-cell icon="server-fill" title="联系客服" isLink></uv-cell>
|
||||||
|
<uv-cell icon="more-circle-fill" title="加盟卡叔" url="/pagesA/JoiningUs/JoiningUs" isLink></uv-cell>
|
||||||
|
<uv-cell v-if="userStore.userInfo.identitys && userStore.userInfo.identitys.some(item => item.code==='superadmin' || item.code==='enterprise')" icon="order" title="企业门店列表" url="/pagesA/StoreManage/StoreList" isLink></uv-cell>
|
||||||
|
<uv-cell v-if="userStore.userInfo.identitys && userStore.userInfo.identitys.some(item => item.code==='superadmin' || item.code==='enterprise') && userStore.userInfo.jurisdictions && userStore.userInfo.jurisdictions.some(item => item.code==='superadmin')" icon="calendar" title="企业门店审核" url="/pagesA/StoreManage/StoreReview" isLink></uv-cell>
|
||||||
|
<!-- <uv-cell icon="edit-pen-fill" title="公司简介" isLink></uv-cell> -->
|
||||||
|
<!-- <uv-cell icon="file-text-fill" title="文件管理" isLink></uv-cell> -->
|
||||||
|
<uv-cell icon="empty-news" title="隐私政策" url="/pagesA/privacy-policy/privacy-policy" isLink></uv-cell>
|
||||||
|
<uv-cell icon="empty-order" title="用户协议" url="/pagesA/user-agreement/user-agreement" isLink></uv-cell>
|
||||||
|
<uv-cell icon="chat-fill" title="关于我们" isLink></uv-cell>
|
||||||
|
</uv-cell-group>
|
||||||
|
</div>
|
||||||
|
<uv-button v-if="authStore?.isLoggedIn" type="error" text="退出登录" customStyle="margin-top: 20px" @click="() => modal.open()"></uv-button>
|
||||||
|
<uv-modal ref="modal" showCancelButton content='确认退出登录?' @confirm="logout"></uv-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref
|
||||||
|
} from "vue";
|
||||||
|
import HeaderCustom from '/components/HeaderCustom/HeaderCustom.vue'
|
||||||
|
import {
|
||||||
|
useAuthStore,
|
||||||
|
useUserStore
|
||||||
|
} from "@/store";
|
||||||
|
import RPC from "@/utils/request";
|
||||||
|
|
||||||
|
const modal = ref(null)
|
||||||
|
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
authStore.signOut()
|
||||||
|
userStore.setUserInfo({username: "",})
|
||||||
|
modal.value.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLogin = () => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "登录中...",
|
||||||
|
});
|
||||||
|
uni.login({
|
||||||
|
success: function(loginRes) {
|
||||||
|
console.log('loginRes', loginRes);
|
||||||
|
RPC.post('/account/miniprogram/phonelogin', {
|
||||||
|
code: loginRes.code
|
||||||
|
}).then(res => {
|
||||||
|
console.log('phonelogin', res)
|
||||||
|
uni.showToast({
|
||||||
|
title: "登录成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
authStore.setAccessToken(res.token)
|
||||||
|
userStore.setUserInfo(res)
|
||||||
|
}).catch(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "登录失败",
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
font-size: 14px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleBox {
|
||||||
|
height: 90px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 5vw;
|
||||||
|
background-color: #fff;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 3vw;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellBox {
|
||||||
|
:deep(.uv-cell__body) {
|
||||||
|
padding: 20px 5vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.uv-cell__title-text) {
|
||||||
|
color: #000;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,158 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container" ref="backTop">
|
||||||
|
<HeaderCustom title="产品详情" :showBack="true"></HeaderCustom>
|
||||||
|
<!-- <uv-sticky bgColor="#fff" offsetTop="90">
|
||||||
|
<uv-tabs :list="list" @click="clickTab"></uv-tabs>
|
||||||
|
</uv-sticky> -->
|
||||||
|
<div class="contentBox">
|
||||||
|
<video v-if="videoUrl" class="video" :src="videoUrl" controls></video>
|
||||||
|
<image class="img" v-for="item in product_images_list" :key="item" :src="item" mode="widthFix" />
|
||||||
|
<image class="img" v-for="item in qualification_images_list" :key="item" :src="item" mode="widthFix" />
|
||||||
|
</div>
|
||||||
|
<div class="pdf_box">
|
||||||
|
<div class="pdf_item" v-for="(item,index) in product_pdfs_list" :key="item.url" @click="openPdf(item)">
|
||||||
|
<div class="pdf_icon"><uv-icon name="file-text-fill" color="#2979ff" size="48"></uv-icon></div>
|
||||||
|
<div class="nameBox">
|
||||||
|
<div class="name">{{item.name}}</div>
|
||||||
|
<div class="pdfInfoBox">
|
||||||
|
<div class="size">{{item.size}}MB</div>
|
||||||
|
<div class="date">{{item.date}}</div>
|
||||||
|
<!-- <div class="time">{{item.time}}</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<uv-back-top :scroll-top="scrollTop"></uv-back-top>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref
|
||||||
|
} from "vue";
|
||||||
|
|
||||||
|
import {
|
||||||
|
onPageScroll,
|
||||||
|
onShow
|
||||||
|
} from "@dcloudio/uni-app";
|
||||||
|
import RPC from "@/utils/request";
|
||||||
|
import HeaderCustom from '/components/HeaderCustom/HeaderCustom.vue'
|
||||||
|
const props = defineProps({
|
||||||
|
id: [String]
|
||||||
|
});
|
||||||
|
console.log('props', props.id)
|
||||||
|
|
||||||
|
const list = ref([])
|
||||||
|
|
||||||
|
const videoUrl = ref('')
|
||||||
|
const images = ref([])
|
||||||
|
|
||||||
|
const clickTab = item => {
|
||||||
|
// console.log(item)
|
||||||
|
videoUrl.value = item.video || ''
|
||||||
|
images.value = item.images || []
|
||||||
|
}
|
||||||
|
|
||||||
|
const product_images_list = ref([])
|
||||||
|
const qualification_images_list = ref([])
|
||||||
|
const product_pdfs_list = ref([])
|
||||||
|
|
||||||
|
const openPdf = (item) => {
|
||||||
|
uni.downloadFile({
|
||||||
|
url: item.url,
|
||||||
|
success: function (res) {
|
||||||
|
var filePath = res.tempFilePath;
|
||||||
|
uni.openDocument({
|
||||||
|
filePath: filePath,
|
||||||
|
showMenu: true,
|
||||||
|
success: function (res) {
|
||||||
|
console.log('打开文档成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDetail = () => {
|
||||||
|
RPC.post('/store/detail', {
|
||||||
|
id: Number(props.id)
|
||||||
|
}).then(res => {
|
||||||
|
console.log('/store/detail', res)
|
||||||
|
// list.value = res.categories?.map(item => {
|
||||||
|
// return {
|
||||||
|
// ...item,
|
||||||
|
// images:item.images ? JSON.parse(item.images) : []
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
videoUrl.value = res?.store?.video_intro || ''
|
||||||
|
product_images_list.value = res?.store?.product_images ? res?.store?.product_images.split(',') : []
|
||||||
|
qualification_images_list.value = res?.store?.qualification_images ? res?.store?.qualification_images.split(',') : []
|
||||||
|
product_pdfs_list.value = res?.store?.product_pdfs ? JSON.parse(res?.store?.product_pdfs) : []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => getDetail())
|
||||||
|
|
||||||
|
const scrollTop = ref(0)
|
||||||
|
onPageScroll((e) => {
|
||||||
|
scrollTop.value = e.scrollTop;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
font-size: 14px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentBox {
|
||||||
|
.video {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pdf_box {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
.pdf_item {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
position: relative;
|
||||||
|
.pdf_icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 16%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.nameBox {
|
||||||
|
flex:1;
|
||||||
|
.name {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.pdfInfoBox {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.date {
|
||||||
|
margin: 0 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,362 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container" ref="backTop">
|
||||||
|
<HeaderCustom title="门店企业列表" :showBack="true"></HeaderCustom>
|
||||||
|
<uv-sticky bgColor="#fff" offsetTop="90">
|
||||||
|
<div class="tabBox">
|
||||||
|
<div class="tabItem" :class="{selected:active==='门店'}" @click="() => active = '门店'">门店</div>
|
||||||
|
<div class="tabItem" :class="{selected:active==='企业'}" @click="() => active = '企业'">企业</div>
|
||||||
|
</div>
|
||||||
|
</uv-sticky>
|
||||||
|
<div class="contentBox" v-show="active==='门店'">
|
||||||
|
<div class="contentItem" v-for="(item,index) in storeList" :key="item.id" @click="goDetail(item.id)">
|
||||||
|
<div class="statusBox" v-if="item.status == 2">
|
||||||
|
<uv-icon name="checkmark-circle-fill" color="#6AD307" size="12"></uv-icon>
|
||||||
|
已通过
|
||||||
|
</div>
|
||||||
|
<div class="statusBox reject" v-if="item.status == 3">
|
||||||
|
<uv-icon name="close-circle-fill" color="#F40404" size="12"></uv-icon>
|
||||||
|
已驳回
|
||||||
|
</div>
|
||||||
|
<div class="statusBox pedding" v-if="item.status == 1">
|
||||||
|
<uv-icon name="clock-fill" color="#F49843" size="12"></uv-icon>
|
||||||
|
待审核
|
||||||
|
</div>
|
||||||
|
<div class="title">{{item.store_name}}</div>
|
||||||
|
<div class="infoBox">
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">地区:{{item.location}}</div>
|
||||||
|
<div class="infoItem">地址详情:{{item.address}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">电话:{{item.contact_phone}}</div>
|
||||||
|
<div class="infoItem">工作时间:{{item.business_hours}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">业务类型:{{item.tags}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">
|
||||||
|
注册日期:{{item.created_at ? dayjs(item.created_at * 1000).format('YYYY-MM-DD HH:mm:ss') : ''}}
|
||||||
|
</div>
|
||||||
|
<div class="infoItem" v-if="item.status == 3">驳回原因:{{item.review_note}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttonBox">
|
||||||
|
<uv-button v-if="item.status != 1" size="small" shape="circle" text="删除" @click="delStore(item)"></uv-button>
|
||||||
|
<uv-button @click="goAdd(item.id)" customStyle="margin-left:10px" size="small" type="primary" shape="circle" text="修改"
|
||||||
|
v-if="item.status != 1"></uv-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<uv-load-more @loadmore="storeGetMore" :status="storeloadingStatus" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contentBox" v-show="active==='企业'">
|
||||||
|
<div class="contentItem" v-for="(item,index) in businessList" :key="item.id">
|
||||||
|
<div class="statusBox" v-if="item.status == 2">
|
||||||
|
<uv-icon name="checkmark-circle-fill" color="#6AD307" size="12"></uv-icon>
|
||||||
|
已通过
|
||||||
|
</div>
|
||||||
|
<div class="statusBox reject" v-if="item.status == 3">
|
||||||
|
<uv-icon name="close-circle-fill" color="#F40404" size="12"></uv-icon>
|
||||||
|
已驳回
|
||||||
|
</div>
|
||||||
|
<div class="statusBox pedding" v-if="item.status == 1">
|
||||||
|
<uv-icon name="clock-fill" color="#F49843" size="12"></uv-icon>
|
||||||
|
待审核
|
||||||
|
</div>
|
||||||
|
<div class="title">{{item.company_name}}</div>
|
||||||
|
<div class="infoBox">
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">姓名:{{item.contact_person}}</div>
|
||||||
|
<div class="infoItem">邮箱:{{item.contact_email}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">手机号码:{{item.contact_phone}}</div>
|
||||||
|
<div class="infoItem">地址:{{item.address}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">更新日期:{{item.updated_at ? dayjs(item.updated_at * 1000).format('YYYY-MM-DD HH:mm:ss') : ''}}</div>
|
||||||
|
<div class="infoItem" v-if="item.status == 3">驳回原因:{{item.review_note}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttonBox">
|
||||||
|
<uv-button size="small" shape="circle" v-if="item.status != 1" text="删除" @click="delStore(item)"></uv-button>
|
||||||
|
<uv-button v-if="item.status != 1" customStyle="margin-left:10px" size="small" type="primary" shape="circle"
|
||||||
|
text="修改" @click="goEdit(item.id)"></uv-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<uv-load-more @loadmore="businessGetMore" :status="businessloadingStatus" />
|
||||||
|
</div>
|
||||||
|
<div class="addBox" @click="goAdd(null)" v-if="active==='门店'"><uv-button iconColor="#fff" iconSize="14" icon="plus" type="primary"
|
||||||
|
shape="circle" text="新增"></uv-button></div>
|
||||||
|
<uv-modal showCancelButton ref="modal" content='确认删除?' :asyncClose="true" @confirm="confirmDel"></uv-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref
|
||||||
|
} from "vue";
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
onShow,
|
||||||
|
onReachBottom
|
||||||
|
} from "@dcloudio/uni-app";
|
||||||
|
import RPC from "@/utils/request";
|
||||||
|
import HeaderCustom from '/components/HeaderCustom/HeaderCustom.vue'
|
||||||
|
|
||||||
|
import {
|
||||||
|
useAuthStore
|
||||||
|
} from "@/store";
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
// const props = defineProps({
|
||||||
|
// id: [String]
|
||||||
|
// });
|
||||||
|
// console.log('props', props.id)
|
||||||
|
const goAdd = (id) => {
|
||||||
|
uni.$uv.route({
|
||||||
|
url: '/pagesA/StoreManage/AddStore',
|
||||||
|
params: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const goEdit = (id) => {
|
||||||
|
uni.$uv.route({
|
||||||
|
url: '/pagesA/StoreManage/businessEdit',
|
||||||
|
params: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const goDetail = (id) => {
|
||||||
|
uni.$uv.route({
|
||||||
|
url: '/pagesA/ProductDetails/ProductDetails',
|
||||||
|
params: {
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const active = ref('门店')
|
||||||
|
const modal = ref(null)
|
||||||
|
|
||||||
|
const storeList = ref([])
|
||||||
|
const storeloadingStatus = ref('loadmore')
|
||||||
|
const storePage = ref(1)
|
||||||
|
const storeCount = ref(0)
|
||||||
|
|
||||||
|
const businessList = ref([])
|
||||||
|
const businessloadingStatus = ref('loadmore')
|
||||||
|
const businessPage = ref(1)
|
||||||
|
const businessCount = ref(0)
|
||||||
|
|
||||||
|
const confirmDel = () => {
|
||||||
|
if (active.value === '门店') {
|
||||||
|
RPC.post('/store/delete', {
|
||||||
|
id: currentItem.value.id
|
||||||
|
}).then((res) => {
|
||||||
|
storeList.value = storeList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '删除成功'
|
||||||
|
})
|
||||||
|
modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (active.value === '企业') {
|
||||||
|
RPC.post('/enterprise/delete', {
|
||||||
|
id: currentItem.value.id
|
||||||
|
}).then((res) => {
|
||||||
|
businessList.value = businessList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '删除成功'
|
||||||
|
})
|
||||||
|
modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentItem = ref({})
|
||||||
|
const delStore = item => {
|
||||||
|
currentItem.value = item
|
||||||
|
modal.value.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStoreList = () => {
|
||||||
|
storeloadingStatus.value === 'loading'
|
||||||
|
RPC.post('/store/list', {
|
||||||
|
page: storePage.value,
|
||||||
|
limit: 20
|
||||||
|
}).then((res) => {
|
||||||
|
storeList.value = [...storeList.value, ...res.rows || []]
|
||||||
|
storeCount.value = res.count || 0
|
||||||
|
if (storeList.value.length >= storeCount.value) {
|
||||||
|
storeloadingStatus.value = 'nomore'
|
||||||
|
} else {
|
||||||
|
storeloadingStatus.value = 'loadmore'
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
storeloadingStatus.value = 'loadmore'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const storeGetMore = () => {
|
||||||
|
if (storeList.value.length >= storeCount.value || storeloadingStatus.value === 'loading') return
|
||||||
|
storeloadingStatus.value = 'loading';
|
||||||
|
storePage.value = ++storePage.value;
|
||||||
|
getStoreList()
|
||||||
|
}
|
||||||
|
// getStoreList()
|
||||||
|
|
||||||
|
const getBusinessList = () => {
|
||||||
|
businessloadingStatus.value === 'loading'
|
||||||
|
RPC.post('/enterprise/list', {
|
||||||
|
page: businessPage.value,
|
||||||
|
limit: 20
|
||||||
|
}).then((res) => {
|
||||||
|
businessList.value = [...businessList.value, ...res.rows || []]
|
||||||
|
businessCount.value = res.count || 0
|
||||||
|
if (businessList.value.length >= businessCount.value) {
|
||||||
|
businessloadingStatus.value = 'nomore'
|
||||||
|
} else {
|
||||||
|
businessloadingStatus.value = 'loadmore'
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
businessloadingStatus.value = 'loadmore'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const businessGetMore = () => {
|
||||||
|
if (businessList.value.length >= businessCount.value || businessloadingStatus.value === 'loading') return
|
||||||
|
businessloadingStatus.value = 'loading';
|
||||||
|
businessPage.value = ++businessPage.value;
|
||||||
|
getBusinessList()
|
||||||
|
}
|
||||||
|
getBusinessList()
|
||||||
|
|
||||||
|
onReachBottom(() => {
|
||||||
|
console.log('shangladaodi')
|
||||||
|
if (active.value === '门店') {
|
||||||
|
storeGetMore()
|
||||||
|
}
|
||||||
|
if (active.value === '企业') {
|
||||||
|
businessGetMore()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (!authStore?.isLoggedIn) {
|
||||||
|
uni.switchTab({
|
||||||
|
url: `/pages/index/index`,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "请先登录",
|
||||||
|
icon: "none",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
storeList.value = []
|
||||||
|
storePage.value = 1
|
||||||
|
getStoreList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
font-size: 14px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabBox {
|
||||||
|
height: 50px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.tabItem {
|
||||||
|
height: 100%;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
color: #5479ED;
|
||||||
|
border-bottom: 1px solid #5479ED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentBox {
|
||||||
|
padding: 10px 14px 54px;
|
||||||
|
|
||||||
|
.contentItem {
|
||||||
|
position: relative;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0px 2px 23px 0px rgba(217, 217, 217, 0.5);
|
||||||
|
|
||||||
|
.statusBox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 4px 8px 4px 12px;
|
||||||
|
width: 56px;
|
||||||
|
color: #6AD307;
|
||||||
|
background-color: #E4FBE9;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
border-radius: 0 0 0 20px;
|
||||||
|
|
||||||
|
&.reject {
|
||||||
|
color: #F40404;
|
||||||
|
background-color: #FAE6E3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pedding {
|
||||||
|
color: #F49843;
|
||||||
|
background-color: #FBF3E5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoBox {
|
||||||
|
.line {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
.infoItem {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #A7A7A7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonBox {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addBox {
|
||||||
|
position: fixed;
|
||||||
|
width: calc(100% - 28px);
|
||||||
|
left: 14px;
|
||||||
|
bottom: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,363 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container" ref="backTop">
|
||||||
|
<HeaderCustom title="门店新增" :showBack="true"></HeaderCustom>
|
||||||
|
<uv-sticky bgColor="#fff" offsetTop="90">
|
||||||
|
<div class="tabBox">
|
||||||
|
<div class="tabItem" :class="{selected:active==='门店'}" @click="() => active = '门店'">门店</div>
|
||||||
|
<div class="tabItem" :class="{selected:active==='企业'}" @click="() => active = '企业'">企业</div>
|
||||||
|
</div>
|
||||||
|
</uv-sticky>
|
||||||
|
<div class="contentBox" v-show="active==='门店'">
|
||||||
|
<div class="contentItem" v-for="(item,index) in storeList" :key="item.id">
|
||||||
|
<div class="title">{{item.store_name}}</div>
|
||||||
|
<div class="infoBox">
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">地区:{{item.location}}</div>
|
||||||
|
<div class="infoItem">地址详情:{{item.address}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">电话:{{item.contact_phone}}</div>
|
||||||
|
<div class="infoItem">工作时间:{{item.business_hours}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">业务类型:{{item.tags}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">
|
||||||
|
注册日期:{{item.created_at ? dayjs(item.created_at * 1000).format('YYYY-MM-DD HH:mm:ss') : ''}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttonBox">
|
||||||
|
<uv-button size="small" type="error" shape="circle" text="驳回" @click="handleReject(item)"></uv-button>
|
||||||
|
<uv-button customStyle="margin-left:10px" size="small" type="primary" shape="circle" text="通过" @click="handlePass(item)"></uv-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<uv-load-more @loadmore="storeGetMore" :status="storeloadingStatus" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contentBox" v-show="active==='企业'">
|
||||||
|
<div class="contentItem" v-for="(item,index) in businessList" :key="item.id">
|
||||||
|
<div class="title">{{item.company_name}}</div>
|
||||||
|
<div class="infoBox">
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">姓名:{{item.contact_person}}</div>
|
||||||
|
<div class="infoItem">邮箱:{{item.contact_email}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">手机号码:{{item.contact_phone}}</div>
|
||||||
|
<div class="infoItem">地址:{{item.address}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<div class="infoItem">更新日期:{{item.updated_at ? dayjs(item.updated_at * 1000).format('YYYY-MM-DD HH:mm:ss') : ''}}</div>
|
||||||
|
<div class="infoItem" v-if="item.status == 3">驳回原因:{{item.review_note}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttonBox">
|
||||||
|
<uv-button size="small" type="error" shape="circle" text="驳回" @click="handleReject(item)"></uv-button>
|
||||||
|
<uv-button customStyle="margin-left:10px" size="small" type="primary" shape="circle"
|
||||||
|
text="通过" @click="handlePass(item)"></uv-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<uv-load-more @loadmore="businessGetMore" :status="businessloadingStatus" />
|
||||||
|
</div>
|
||||||
|
<uv-modal showCancelButton ref="modal" content='确认通过?' :asyncClose="true" @confirm="confirmPass"></uv-modal>
|
||||||
|
<uv-modal showCancelButton ref="reject_modal" :asyncClose="true" @confirm="confirmReject">
|
||||||
|
<view class="slot-content">
|
||||||
|
<uv-input placeholder="请输入驳回原因" border="surround" v-model="reject_note"></uv-input>
|
||||||
|
</view>
|
||||||
|
</uv-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref
|
||||||
|
} from "vue";
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import {
|
||||||
|
onShow,
|
||||||
|
onReachBottom
|
||||||
|
} from "@dcloudio/uni-app";
|
||||||
|
import RPC from "@/utils/request";
|
||||||
|
import HeaderCustom from '/components/HeaderCustom/HeaderCustom.vue'
|
||||||
|
import {
|
||||||
|
useAuthStore
|
||||||
|
} from "@/store";
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
// const props = defineProps({
|
||||||
|
// id: [String]
|
||||||
|
// });
|
||||||
|
// console.log('props', props.id)
|
||||||
|
|
||||||
|
const active = ref('门店')
|
||||||
|
const modal = ref(null)
|
||||||
|
|
||||||
|
const reject_note = ref('')
|
||||||
|
const reject_modal = ref(null)
|
||||||
|
|
||||||
|
const storeList = ref([])
|
||||||
|
const storeloadingStatus = ref('loadmore')
|
||||||
|
const storePage = ref(1)
|
||||||
|
const storeCount = ref(0)
|
||||||
|
|
||||||
|
const businessList = ref([])
|
||||||
|
const businessloadingStatus = ref('loadmore')
|
||||||
|
const businessPage = ref(1)
|
||||||
|
const businessCount = ref(0)
|
||||||
|
|
||||||
|
const confirmPass = () => {
|
||||||
|
if (active.value === '门店') {
|
||||||
|
RPC.post('/store/review', {
|
||||||
|
id: currentItem.value.id,
|
||||||
|
status:2
|
||||||
|
}).then((res) => {
|
||||||
|
storeList.value = storeList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '通过成功'
|
||||||
|
})
|
||||||
|
modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (active.value === '企业') {
|
||||||
|
RPC.post('/enterprise/review', {
|
||||||
|
id: currentItem.value.id,
|
||||||
|
status:2
|
||||||
|
}).then((res) => {
|
||||||
|
businessList.value = businessList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '通过成功'
|
||||||
|
})
|
||||||
|
modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const confirmReject = () => {
|
||||||
|
if(!reject_note.value) {
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '请填写驳回原因'
|
||||||
|
})
|
||||||
|
reject_modal.value.closeLoading()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (active.value === '门店') {
|
||||||
|
RPC.post('/store/review', {
|
||||||
|
id: currentItem.value.id,
|
||||||
|
status:3,
|
||||||
|
note:reject_note.value
|
||||||
|
}).then((res) => {
|
||||||
|
storeList.value = storeList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '驳回成功',
|
||||||
|
})
|
||||||
|
reject_modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
reject_modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (active.value === '企业') {
|
||||||
|
RPC.post('/enterprise/review', {
|
||||||
|
id: currentItem.value.id,
|
||||||
|
status:3,
|
||||||
|
note:reject_note.value
|
||||||
|
}).then((res) => {
|
||||||
|
businessList.value = businessList.value.filter(item => item.id !== currentItem.value.id)
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'success',
|
||||||
|
title: '驳回成功'
|
||||||
|
})
|
||||||
|
reject_modal.value.close()
|
||||||
|
}).catch(() => {
|
||||||
|
reject_modal.value.closeLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentItem = ref({})
|
||||||
|
const handlePass = item => {
|
||||||
|
currentItem.value = item
|
||||||
|
modal.value.open();
|
||||||
|
}
|
||||||
|
const handleReject = item => {
|
||||||
|
reject_note.value = ''
|
||||||
|
currentItem.value = item
|
||||||
|
reject_modal.value.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStoreList = () => {
|
||||||
|
storeloadingStatus.value === 'loading'
|
||||||
|
RPC.post('/store/pending_list', {
|
||||||
|
page: storePage.value,
|
||||||
|
limit: 20
|
||||||
|
}).then((res) => {
|
||||||
|
storeList.value = [...storeList.value, ...res.rows || []]
|
||||||
|
storeCount.value = res.count || 0
|
||||||
|
if (storeList.value.length >= storeCount.value) {
|
||||||
|
storeloadingStatus.value = 'nomore'
|
||||||
|
} else {
|
||||||
|
storeloadingStatus.value = 'loadmore'
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
storeloadingStatus.value = 'loadmore'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const storeGetMore = () => {
|
||||||
|
if (storeList.value.length >= storeCount.value || storeloadingStatus.value === 'loading') return
|
||||||
|
storeloadingStatus.value = 'loading';
|
||||||
|
storePage.value = ++storePage.value;
|
||||||
|
getStoreList()
|
||||||
|
}
|
||||||
|
getStoreList()
|
||||||
|
|
||||||
|
const getBusinessList = () => {
|
||||||
|
businessloadingStatus.value === 'loading'
|
||||||
|
RPC.post('/enterprise/pending', {
|
||||||
|
page: businessPage.value,
|
||||||
|
limit: 20
|
||||||
|
}).then((res) => {
|
||||||
|
businessList.value = [...businessList.value, ...res.rows || []]
|
||||||
|
businessCount.value = res.count || 0
|
||||||
|
if (businessList.value.length >= businessCount.value) {
|
||||||
|
businessloadingStatus.value = 'nomore'
|
||||||
|
} else {
|
||||||
|
businessloadingStatus.value = 'loadmore'
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
businessloadingStatus.value = 'loadmore'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const businessGetMore = () => {
|
||||||
|
if (businessList.value.length >= businessCount.value || businessloadingStatus.value === 'loading') return
|
||||||
|
businessloadingStatus.value = 'loading';
|
||||||
|
businessPage.value = ++businessPage.value;
|
||||||
|
getBusinessList()
|
||||||
|
}
|
||||||
|
getBusinessList()
|
||||||
|
|
||||||
|
onReachBottom(() => {
|
||||||
|
console.log('shangladaodi')
|
||||||
|
if (active.value === '门店') {
|
||||||
|
storeGetMore()
|
||||||
|
}
|
||||||
|
if (active.value === '企业') {
|
||||||
|
businessGetMore()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (!authStore?.isLoggedIn) {
|
||||||
|
uni.switchTab({
|
||||||
|
url: `/pages/index/index`,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "请先登录",
|
||||||
|
icon: "none",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container {
|
||||||
|
font-size: 14px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabBox {
|
||||||
|
height: 50px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.tabItem {
|
||||||
|
height: 100%;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
color: #5479ED;
|
||||||
|
border-bottom: 1px solid #5479ED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentBox {
|
||||||
|
padding: 10px 14px 54px;
|
||||||
|
|
||||||
|
.contentItem {
|
||||||
|
position: relative;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0px 2px 23px 0px rgba(217, 217, 217, 0.5);
|
||||||
|
|
||||||
|
.statusBox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 4px 8px 4px 12px;
|
||||||
|
width: 56px;
|
||||||
|
color: #6AD307;
|
||||||
|
background-color: #E4FBE9;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
border-radius: 0 0 0 20px;
|
||||||
|
|
||||||
|
&.reject {
|
||||||
|
color: #F40404;
|
||||||
|
background-color: #FAE6E3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pedding {
|
||||||
|
color: #F49843;
|
||||||
|
background-color: #FBF3E5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoBox {
|
||||||
|
.line {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
.infoItem {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #A7A7A7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonBox {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addBox {
|
||||||
|
position: fixed;
|
||||||
|
width: calc(100% - 28px);
|
||||||
|
left: 14px;
|
||||||
|
bottom: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { setupI18n } from "@/locale";
|
||||||
|
import { setupStore } from "@/store";
|
||||||
|
import { setupPermission } from "./permission";
|
||||||
|
import { setupUI } from "./ui";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(app) {
|
||||||
|
// UI扩展配置
|
||||||
|
app.use(setupUI);
|
||||||
|
// 状态管理
|
||||||
|
app.use(setupStore);
|
||||||
|
// 国际化
|
||||||
|
app.use(setupI18n);
|
||||||
|
// 路由拦截
|
||||||
|
app.use(setupPermission);
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
import pagesJson from "@/pages.json";
|
||||||
|
|
||||||
|
// 路径常量
|
||||||
|
export const HOME_PATH = "/pages/index/index";
|
||||||
|
export const LOGIN_PATH = "/pages/login/login";
|
||||||
|
export const ERROR404_PATH = "/pages/404/404";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析路由地址
|
||||||
|
* @param {object} pagesJson
|
||||||
|
* @returns [{"path": "/pages/index/index","needLogin": false},...]
|
||||||
|
*/
|
||||||
|
function parseRoutes(pagesJson = {}) {
|
||||||
|
if (!pagesJson.pages) {
|
||||||
|
pagesJson.pages = [];
|
||||||
|
}
|
||||||
|
if (!pagesJson.subPackages) {
|
||||||
|
pagesJson.subPackages = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePages(pages = [], rootPath = "") {
|
||||||
|
const routes = [];
|
||||||
|
for (let i = 0; i < pages.length; i++) {
|
||||||
|
routes.push({
|
||||||
|
path: rootPath ? `/${rootPath}/${pages[i].path}` : `/${pages[i].path}`,
|
||||||
|
needLogin: pages[i].needLogin === true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSubPackages(subPackages = []) {
|
||||||
|
const routes = [];
|
||||||
|
for (let i = 0; i < subPackages.length; i++) {
|
||||||
|
routes.push(...parsePages(subPackages[i].pages, subPackages[i].root));
|
||||||
|
}
|
||||||
|
return routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
...parsePages(pagesJson.pages),
|
||||||
|
...parseSubPackages(pagesJson.subPackages),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
export const routes = parseRoutes(pagesJson);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前路由
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
export function currentRoute() {
|
||||||
|
const pages = getCurrentPages();
|
||||||
|
if (pages.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentPage = pages[pages.length - 1];
|
||||||
|
return currentPage?.$page?.fullPath || currentPage.route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除查询字符串
|
||||||
|
* @param {String} path
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function removeQueryString(path = "") {
|
||||||
|
return path.split("?")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径是否存在
|
||||||
|
* @param {String} path
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function isPathExists(path = "") {
|
||||||
|
const cleanPath = removeQueryString(path);
|
||||||
|
return routes.some((item) => item.path === cleanPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是tabbar页面路径
|
||||||
|
* @param {String} path
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function isTabBarPath(path = "") {
|
||||||
|
const cleanPath = removeQueryString(path);
|
||||||
|
return (
|
||||||
|
pagesJson.tabBar?.list?.some(
|
||||||
|
(item) => `/${item.pagePath}` === cleanPath
|
||||||
|
) === true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1,12 @@
|
|||||||
|
import { createPinia } from "pinia";
|
||||||
|
|
||||||
|
const store = createPinia();
|
||||||
|
|
||||||
|
export function setupStore(app) {
|
||||||
|
app.use(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { store };
|
||||||
|
|
||||||
|
export * from "./modules/user";
|
||||||
|
export * from "./modules/auth";
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
import AuthAPI from "@/api/modules/auth";
|
||||||
|
import { store } from "@/store";
|
||||||
|
import { cache } from "@/utils/cache";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { computed, ref, watch } from "vue";
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore("auth", () => {
|
||||||
|
const ACCESS_TOKEN_KEY = "accessToken";
|
||||||
|
const REFRESH_TOKEN_KEY = "refreshToken";
|
||||||
|
const accessToken = ref(cache(ACCESS_TOKEN_KEY) ?? "");
|
||||||
|
const refreshToken = ref(cache(REFRESH_TOKEN_KEY) ?? "");
|
||||||
|
const isLoggedIn = computed(() => !!accessToken.value);
|
||||||
|
|
||||||
|
watch(accessToken, (newValue) => cache(ACCESS_TOKEN_KEY, newValue || null));
|
||||||
|
watch(refreshToken, (newValue) => cache(REFRESH_TOKEN_KEY, newValue || null));
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
async function signUp(payload) {
|
||||||
|
const response = await AuthAPI.signUp(payload);
|
||||||
|
const prefix = response.tokenType ? `${response.tokenType} ` : "";
|
||||||
|
accessToken.value = prefix + response.accessToken;
|
||||||
|
refreshToken.value = prefix + response.refreshToken;
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
async function signIn(payload) {
|
||||||
|
const response = await AuthAPI.signIn(payload);
|
||||||
|
const prefix = response.tokenType ? `${response.tokenType} ` : "";
|
||||||
|
accessToken.value = prefix + response.accessToken;
|
||||||
|
refreshToken.value = prefix + response.refreshToken;
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登出
|
||||||
|
function signOut() {
|
||||||
|
accessToken.value = "";
|
||||||
|
refreshToken.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新token
|
||||||
|
async function refresh(payload) {
|
||||||
|
const response = await AuthAPI.refreshToken(payload);
|
||||||
|
const prefix = response.tokenType ? `${response.tokenType} ` : "";
|
||||||
|
accessToken.value = prefix + response.accessToken;
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAccessToken(payload) {
|
||||||
|
accessToken.value = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
isLoggedIn,
|
||||||
|
signUp,
|
||||||
|
signIn,
|
||||||
|
signOut,
|
||||||
|
refresh,
|
||||||
|
setAccessToken
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 手动提供给 useStore() 函数 pinia 实例
|
||||||
|
// https://pinia.vuejs.org/zh/core-concepts/outside-component-usage.html#using-a-store-outside-of-a-component
|
||||||
|
export function useAuthStoreHook() {
|
||||||
|
return useAuthStore(store);
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { cache } from "@/utils/cache";
|
||||||
|
|
||||||
|
export const useUserStore = defineStore("user", () => {
|
||||||
|
const userInfo = ref(cache('USERINFO_KEY') ? JSON.parse(cache('USERINFO_KEY')) : {
|
||||||
|
username: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const adressInfo = ref(cache('ADRESS_KEY') ? JSON.parse(cache('ADRESS_KEY')) : {
|
||||||
|
latitude: "",
|
||||||
|
longitude: "",
|
||||||
|
adress: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(userInfo, (newValue) => cache('USERINFO_KEY', newValue ? JSON.stringify(newValue) : null));
|
||||||
|
watch(adressInfo, (newValue) => cache('ADRESS_KEY', newValue ? JSON.stringify(newValue) : null));
|
||||||
|
|
||||||
|
function setUserInfo(payload) {
|
||||||
|
userInfo.value = payload;
|
||||||
|
}
|
||||||
|
function setAdressInfo(payload) {
|
||||||
|
adressInfo.value = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
userInfo,
|
||||||
|
setUserInfo,
|
||||||
|
adressInfo,
|
||||||
|
setAdressInfo
|
||||||
|
};
|
||||||
|
});
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"jsxFactory": "h",
|
||||||
|
"jsxFragmentFactory": "Fragment",
|
||||||
|
"jsxImportSource": "vue",
|
||||||
|
"lib": ["esnext", "dom"],
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noLib": false,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
},
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"target": "esnext",
|
||||||
|
"types": ["@dcloudio/types"],
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"verbatimModuleSyntax": true
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "uni_modules", "unpackage", "**/*.js"],
|
||||||
|
"include": ["**/*.{ts,vue}"]
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"id": "uv-album",
|
||||||
|
"displayName": "uv-album 相册 全面兼容vue3+2、app、h5、小程序等多端",
|
||||||
|
"version": "1.0.4",
|
||||||
|
"description": "本组件提供一个类似相册的功能,让开发者开发起来更加得心应手,功能齐全,灵活配置可以,开箱即用。减少重复的模板代码",
|
||||||
|
"keywords": [
|
||||||
|
"album",
|
||||||
|
"uv-ui",
|
||||||
|
"uvui",
|
||||||
|
"相册",
|
||||||
|
"图片"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "插件不采集任何数据",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [
|
||||||
|
"uv-ui-tools",
|
||||||
|
"uv-text"
|
||||||
|
],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"id": "uv-alert",
|
||||||
|
"displayName": "uv-alert 警告提示 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"description": "uv-alert 警告提示,展现需要关注的信息。灵活配置,功能齐全,兼容全端",
|
||||||
|
"keywords": [
|
||||||
|
"alert",
|
||||||
|
"uvui",
|
||||||
|
"uv-ui",
|
||||||
|
"警告提示"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "插件不采集任何数据",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [
|
||||||
|
"uv-ui-tools",
|
||||||
|
"uv-transition",
|
||||||
|
"uv-icon"
|
||||||
|
],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 头像图片组
|
||||||
|
urls: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
// 最多展示的头像数量
|
||||||
|
maxCount: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 5
|
||||||
|
},
|
||||||
|
// 头像形状
|
||||||
|
shape: {
|
||||||
|
type: String,
|
||||||
|
default: 'circle'
|
||||||
|
},
|
||||||
|
// 图片裁剪模式
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'scaleToFill'
|
||||||
|
},
|
||||||
|
// 超出maxCount时是否显示查看更多的提示
|
||||||
|
showMore: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 头像大小
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 40
|
||||||
|
},
|
||||||
|
// 指定从数组的对象元素中读取哪个属性作为图片地址
|
||||||
|
keyName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 头像之间的遮挡比例
|
||||||
|
gap: {
|
||||||
|
type: [String, Number],
|
||||||
|
validator(value) {
|
||||||
|
return value >= 0 && value <= 1
|
||||||
|
},
|
||||||
|
default: 0.5
|
||||||
|
},
|
||||||
|
// 需额外显示的值
|
||||||
|
extraValue: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
...uni.$uv?.props?.avatarGroup
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"id": "uv-avatar",
|
||||||
|
"displayName": "uv-avatar 头像 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||||
|
"version": "1.0.5",
|
||||||
|
"description": "uv-avatar 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。",
|
||||||
|
"keywords": [
|
||||||
|
"uv-avatar",
|
||||||
|
"uvui",
|
||||||
|
"uv-ui",
|
||||||
|
"avatar",
|
||||||
|
"头像"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "插件不采集任何数据",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [
|
||||||
|
"uv-ui-tools",
|
||||||
|
"uv-icon",
|
||||||
|
"uv-text"
|
||||||
|
],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||