init
|
@ -0,0 +1,138 @@
|
|||
所有交互调用失败原生那边进行toast提示,不用进行详细说明原因, 提示下XX调用(获取)失败
|
||||
泛型中string[`'|'']的是数组 `'|''是字符串
|
||||
所有的方法名字和参数名字都是驼峰,第一个字母小写,Word可能存在问题,自动把第一个字母转成了大写
|
||||
页面全屏可写,到电池状态栏的位置
|
||||
单位:size为kb,宽高为px,时间为秒
|
||||
扫码
|
||||
scanCode
|
||||
入参:Object<{onlyFromCamera:boolean}>
|
||||
onlyFromCamera:是否能从相册选择(默认传false,false为能从相册选择)
|
||||
返回值:Object<result:string>
|
||||
result:扫码内容
|
||||
获取设备信息
|
||||
getSystemInfo
|
||||
返回值:Object<{MEID:string,IMEI:string,deviceBrand:string,osName:string,deviceType:string}>
|
||||
deviceBrand:手机型号 osName:操作系统 deviceType:设备类型(平板、手机)
|
||||
说明:还有其他常用的值也加一下
|
||||
获取电池状态栏的高度
|
||||
getStatusBarHeight
|
||||
返回值:object<{height:number,bottomSafeHeight:number}>
|
||||
height:电池状态栏高度 bottomSafeHeight:苹果手机底部安全区域高度
|
||||
获取消息推送的CID
|
||||
getPushClientId
|
||||
返回值:object<{CID:string}>
|
||||
拍照
|
||||
camera
|
||||
返回值:Object<{path:string,size:number}>
|
||||
path:路径 size:大小(kb)
|
||||
录制视频,时长最大60秒
|
||||
recordVideo
|
||||
返回值:Object<{path:string,size:number,duration:number,height:number,width:number}>
|
||||
path:路径 size:大小(kb) duration:时长(秒) height(px) width(px)
|
||||
相册,选择图片和视频
|
||||
chooseMedia
|
||||
入参:Object<{type:string[`image','video'],count:number,multiple:boolean}>
|
||||
type:选择的类型(默认传image) count:数量(默认传1) multiple:是否多选(默认传true)
|
||||
返回值:Object<{path:string,size:number,duration:number,height:number,width:number,type:string}>[]
|
||||
path:路径 size:大小(kb) duration:时长(秒,只有视频存在,图片的话返回0) height(px) width(px) type:类型(文件类型JPG、png)
|
||||
|
||||
唤起指定摄像头
|
||||
activateCamera
|
||||
入参:object<{camera:'back'|'front',interval:number}>
|
||||
camera:使用哪个摄像头(默认传front) interval:每个几秒进行拍照(默认传3000,单位毫秒)
|
||||
说明:不能选择相册和切换摄像头,每隔几秒定时拍照返回,照片不保存到相册,拍照的时候去掉声音,需要原生写页面,中间画一个宽高相对于屏幕宽度80%的圆形,圆形外面的不显示,模拟人脸验证,圆形上面加一行字,通过activateCameraSetMessage调用,关闭通过activateCameraClose调用
|
||||
获取activateCamera返回值
|
||||
activateCameraGetImage
|
||||
返回值:Object<{path:string,size:number}>[]
|
||||
path:沙盒路径 size:大小(kb)
|
||||
说明:会多次调用,每次调用返回上一次调用到这次调用之间的所有照片
|
||||
关闭activateCamera交互调用
|
||||
activateCameraClose
|
||||
实时更改activateCamera圆形上面的字
|
||||
activateCameraSetMessage
|
||||
入参:object<{message:string}>
|
||||
说明:会多次调用,每次调用都需要更改文字
|
||||
对接各个手机厂商消息推送
|
||||
需要对接的手机厂商:华为、魅族、OPOO、VIVO、荣耀、小米
|
||||
手机桌面数字角标
|
||||
|
||||
setBadgeNumber
|
||||
入参:object<{count:number}>
|
||||
count:显示的数字
|
||||
定位
|
||||
getLocation
|
||||
入参:object<{type:'wgs84'|'gcj02',geocode:boolean}>
|
||||
type:使用的定位类型(默认传gcj02) geocode:是否解析地址信息(默认传false)
|
||||
返回值:Object<{longitude: string,latitude: string,address: {country: string,province: string,city: string,district: string,town: string,street: string,streetNumber: string,poiName: string,postalCode: string,cityCode: string}}>
|
||||
longitude:经度 latitude:纬度 address:地址信息(country:国家 province:省 city:市 district:区 town:镇 street:街道 streetNumber:街道门牌号 poiName:POI信息 postalCode:邮编 cityCode:城市代码)
|
||||
说明:无法获取到的返回空字符串,gcj02的定位SDK使用百度
|
||||
查询是否有权限
|
||||
getPermission
|
||||
入参:object<{type:'camera'|'audio'|'location'|'album',title:string,describe:string}>
|
||||
type:需要查询的权限(camera相机、audio录音、location定位、album相册) title:提示的标题 describe:提示的内容
|
||||
返回值:Object<{code:number}>
|
||||
code:是否有权限(1:已经授权,2:拒绝授权)
|
||||
说明:查询是否有当前权限,没有的话弹窗询问是否同意获取此权限,拒绝无法再次进行弹窗时跳转到系统设置让用户手动授权,还有一些常用的也加一下
|
||||
打开浏览器
|
||||
openBrowser
|
||||
入参:object<{url:string}>
|
||||
url:打开的网址
|
||||
打开第三方app预览附件
|
||||
previewFile
|
||||
入参:object<{url:string}>
|
||||
url:文件地址(文件服务器上的地址)
|
||||
H5部署地址通过请求获取
|
||||
接口地址:https://pm.qhdsafety.com/zy-projectManage/project/getH5?CODE=app
|
||||
返回值:{"result":"success","url":"https://jpfz.qhdsafety.com/demo"}
|
||||
版本更新
|
||||
updateVersion
|
||||
说明:有新版本进行弹窗提示更新,需要原生写弹窗,每次打开app进行一次版本查询,手动查询的时候没有新版本原生进行toast提示(当前已经是最新版本,当前版本号:XXX)
|
||||
接口地址:https://pm.qhdsafety.com/zy-projectManage/projectDetails/findLastVersion?code=app&type=Android
|
||||
type Android和IOS
|
||||
返回值:{"result":"success","file":"123232.apk","version":"1.0"}
|
||||
|
||||
ios AppStore地址:https://apps.apple.com/app/id6469101762
|
||||
关闭app
|
||||
quitApp
|
||||
17.选择文件
|
||||
chooseFile
|
||||
入参:object<{type:'doc'|'docx'|'xls'|'xlsx'|'pdf'|''}>
|
||||
type:选择的文件类型
|
||||
返回值:object<{path:string,type:string,size:number}>
|
||||
path:路径 size:大小(kb) type:文件类型
|
||||
当前网络状态
|
||||
getNetworkType
|
||||
返回值:object<{networkType:string}>(wifi、2g、3g、4g、5g、unknown、none)
|
||||
说明:原生那边进行实时网络状态监测,没有网络的时候进行提示
|
||||
当前app版本
|
||||
getVersion
|
||||
返回值:object<{version:string)
|
||||
version:当前版本
|
||||
app隐藏和显示
|
||||
appShow(不通过桥文件调用,js写全局方法,挂载到window上)
|
||||
appHide(不通过桥文件调用,js写全局方法,挂载到window上)
|
||||
切换页面
|
||||
push(下一页)
|
||||
入参:object<url:string,params:object>
|
||||
url:页面路径 params:携带的参数(对象格式)
|
||||
|
||||
pop(上一页)
|
||||
入参:object<delta:number,params:object>
|
||||
delta:回退几级(默认一级,不进行传值) params:携带的参数(对象格式)
|
||||
|
||||
reLaunch(关闭所有页面,打开新页面)
|
||||
入参:object<url:string,params:object>
|
||||
url:页面路径 params:携带的参数(对象格式)
|
||||
说明:把路由所有堆全部清除,只保留跳转过去这个路由
|
||||
|
||||
redirect(重定向页面)
|
||||
入参:object<url:string,params:object>
|
||||
url:页面路径 params:携带的参数(对象格式)
|
||||
说明:a,b,c三个页面,在b页面调用跳转到c,b页面在路由堆里删除掉,返回的时候直接回到a
|
||||
|
||||
pageShow(当前页面显示)(不通过桥文件调用,js在需要监听的页面的写全局方法,挂载到window上)
|
||||
|
||||
pageHide(当前页面隐藏)(不通过桥文件调用,js在需要监听的页面的写全局方法,挂载到window上)
|
||||
|
||||
initData(获取路由参数)(不通过桥文件调用,js在需要监听的页面的写全局方法,挂载到window上)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
安卓打包
|
||||
1
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
别名和密码
|
||||
keyAlias 'qa'keyPassword '123456'storePassword '123456'
|
||||
|
||||
换名字
|
||||
|
||||
|
||||
|
||||
换图标
|
||||
|
||||
替换这个图片
|
|
@ -0,0 +1 @@
|
|||
VITE_BASE=/
|
|
@ -0,0 +1 @@
|
|||
VITE_BASE=/demo
|
|
@ -0,0 +1,4 @@
|
|||
public
|
||||
dist
|
||||
package.json
|
||||
!.prettierrc.cjs
|
|
@ -0,0 +1,62 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"standard",
|
||||
"@vue/prettier",
|
||||
"eslint:recommended",
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["vue"],
|
||||
rules: {
|
||||
"no-console": "warn",
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-v-html": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"camelcase": "off",
|
||||
"eqeqeq": "error",
|
||||
"vue/no-template-shadow": "error",
|
||||
"vue/attribute-hyphenation": "error",
|
||||
"vue/html-end-tags": "error",
|
||||
"vue/eqeqeq": "error",
|
||||
"vue/component-name-in-template-casing": ["error", "kebab-case"],
|
||||
"vue/enforce-style-attribute": [
|
||||
"error",
|
||||
{ "allow": ["scoped", "module"] }
|
||||
],
|
||||
"vue/v-on-event-hyphenation": ["error", "always",{
|
||||
"autofix": true,
|
||||
}],
|
||||
"vue/require-explicit-emits": "error",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "VariableDeclarator[id.name='pd']",
|
||||
"message": "不允许使用 pd,请改用有语义化的变量名"
|
||||
},
|
||||
{
|
||||
"selector": "ObjectExpression > Property[key.name='pd']",
|
||||
"message": "不允许使用 pd,请改用有语义化的变量名"
|
||||
},
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{ vars: "all", args: "after-used", ignoreRestSiblings: false }
|
||||
],
|
||||
"linebreak-style": ["off",'windows'],
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{ "object": "Object", "property": "assign"}
|
||||
],
|
||||
},
|
||||
globals: {
|
||||
defineOptions: "readonly",
|
||||
},
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
extends: ["@vue/prettier", "plugin:prettier/recommended"],
|
||||
endOfLine: "crlf",
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
# Vue 3 + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
||||
<title>demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<noscript>
|
||||
<strong>很抱歉,如果没有启用JavaScript,网站无法正常工作,请启用JavaScript使其正常工作。</strong>
|
||||
</noscript>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "demo",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue --fix src .prettierrc.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vant/weapp": "^1.11.7",
|
||||
"@vueuse/core": "^10.11.1",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.7.4",
|
||||
"dayjs": "^1.11.12",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.2.1",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qs": "^6.13.0",
|
||||
"throttle-debounce": "^5.0.2",
|
||||
"vant": "^4.9.4",
|
||||
"vue": "^3.4.37",
|
||||
"vue-router": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.3.0",
|
||||
"@vitejs/plugin-vue": "^5.1.2",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"cnjm-postcss-px-to-viewport": "^1.0.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"prettier": "^3.3.3",
|
||||
"sass": "^1.77.8",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vconsole": "^3.15.1",
|
||||
"vite": "^5.4.0",
|
||||
"vite-plugin-checker": "^0.7.2",
|
||||
"vite-plugin-enhance-log": "^0.6.2",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-remove-console": "^2.2.0",
|
||||
"vue-eslint-parser": "^9.4.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
const path = require('path')
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {
|
||||
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8', '> 1%'],
|
||||
grid: true,
|
||||
},
|
||||
"cnjm-postcss-px-to-viewport": {
|
||||
unitToConvert: "px", // 要转化的单位
|
||||
viewportWidth: 750, // UI设计稿的宽度
|
||||
unitPrecision: 6, // 转换后的精度,即小数点位数
|
||||
propList: ["*"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
|
||||
viewportUnit: "vw", // 指定需要转换成的视窗单位,默认vw
|
||||
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw
|
||||
selectorBlackList: [".ignore", ".hairlines"],
|
||||
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
|
||||
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
|
||||
replace: true, // 是否转换后直接更换属性值
|
||||
exclude: [], // 设置忽略文件,用正则做目录名匹配
|
||||
landscape: false, // 是否处理横屏情况
|
||||
// 如果没有使用其他的尺寸来设计,下面这个方法可以不需要,比如vant是375的
|
||||
customFun: ({ file }) => {
|
||||
// 这个自定义的方法是针对处理vant组件下的设计稿为375问题
|
||||
return path.join(file).includes(path.join("node_modules", "vant"))
|
||||
? 375
|
||||
: 750;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<suspense>
|
||||
<template #default>
|
||||
<div>
|
||||
<van-overlay :show="miscellaneousStore.getLoading">
|
||||
<van-loading color="#fff" size="24px" vertical>加载中...</van-loading>
|
||||
</van-overlay>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
<template #fallback>
|
||||
<div>加载中...</div>
|
||||
</template>
|
||||
</suspense>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRoute } from "vue-router";
|
||||
import { watchEffect } from "vue";
|
||||
import { useMiscellaneousStore } from "@/pinia/miscellaneous.js";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { useNativeGetStatusBarHeight } from "@/assets/js/useNative.js";
|
||||
const store = systemInfoStore();
|
||||
const miscellaneousStore = useMiscellaneousStore();
|
||||
const route = useRoute();
|
||||
watchEffect(() => {
|
||||
window.document.title = route.meta.title;
|
||||
});
|
||||
window.appShow = () => {
|
||||
console.log("app显示了");
|
||||
};
|
||||
window.appHide = () => {
|
||||
console.log("app隐藏了");
|
||||
};
|
||||
const getBarHeight = () => {
|
||||
useNativeGetStatusBarHeight({}, (data) => {
|
||||
console.log(data, "电池栏高度");
|
||||
store.setSystemInfo(data.height, "batteryBarsHeight");
|
||||
if (data.bottomSafeHeight) {
|
||||
store.setSystemInfo(data.bottomSafeHeight, "bottomSafeHeight");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getBarHeight();
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:root {
|
||||
--van-uploader-size: 146px !important;
|
||||
--van-button-mini-padding: 0 20px !important;
|
||||
--van-nav-bar-z-index: 9 !important;
|
||||
--van-nav-bar-background: rgb(51, 119, 255) !important;
|
||||
--van-nav-bar-title-text-color: var(--van-white) !important;
|
||||
--van-nav-bar-icon-color: var(--van-white) !important;
|
||||
--van-nav-bar-text-color: var(--van-white) !important;
|
||||
}
|
||||
#app {
|
||||
background-color: #fafafa;
|
||||
min-height: 100vh;
|
||||
font-size: 30px;
|
||||
}
|
||||
.van-loading {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,26 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
overflow: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
// 文字超出几行隐藏,最多5行
|
||||
// 使用超出1行隐藏,如果使用了flex,则需要给父元素设置min-width: 0;
|
||||
@for $i from 1 through 5 {
|
||||
.line-#{$i} {
|
||||
@if $i == 1 {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical !important;
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 479 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
|
@ -0,0 +1,2 @@
|
|||
import mitt from "mitt";
|
||||
export default mitt();
|
|
@ -0,0 +1,34 @@
|
|||
const SHIP_NATIVE = function () {};
|
||||
SHIP_NATIVE.prototype.version = "0.0.1";
|
||||
const clearWindowsEnv = (callback) => {
|
||||
setTimeout(() => {
|
||||
delete window[callback];
|
||||
}, 10);
|
||||
};
|
||||
const sendNative = function (name, params, callback) {
|
||||
const paramsToJson = JSON.stringify({
|
||||
name,
|
||||
params,
|
||||
});
|
||||
if (window.SHIP_ENV === "SHIP_IOS") {
|
||||
const pre = "SHIP_IOS_CALLBACK_";
|
||||
window[pre + name] = (data) => {
|
||||
callback(data || null);
|
||||
clearWindowsEnv(pre + name);
|
||||
};
|
||||
window.webkit.messageHandlers.SHIP_IOS.postMessage(paramsToJson);
|
||||
}
|
||||
if (window.SHIP_ENV === "SHIP_Android") {
|
||||
const callbackName = "SHIP_ANDROID_CALLBACK_" + name;
|
||||
window[callbackName] = (data) => {
|
||||
callback(JSON.parse(data));
|
||||
clearWindowsEnv(callbackName);
|
||||
};
|
||||
window.SHIP_NATIVE_ANDROID.postMessageAndroid(paramsToJson, callbackName);
|
||||
}
|
||||
};
|
||||
SHIP_NATIVE.prototype.requset = function (name, params, callback) {
|
||||
sendNative(name, params, callback);
|
||||
};
|
||||
const SHIP = new SHIP_NATIVE();
|
||||
window.SHIP_NATIVE = SHIP;
|
|
@ -0,0 +1,86 @@
|
|||
import {
|
||||
useNativePopPage,
|
||||
useNativePushPage,
|
||||
useNativeRedirectPage,
|
||||
useNativeReLaunchPage,
|
||||
} from "@/assets/js/useNative.js";
|
||||
import router from "@/router/index.js";
|
||||
|
||||
function getNativeUrl(to, options) {
|
||||
let url =
|
||||
window.location.origin +
|
||||
(import.meta.env.VITE_BASE || "") +
|
||||
(window.location.hash ? "/#" : "") +
|
||||
to.url;
|
||||
if (!options.useNativeParams) {
|
||||
const { href } = router.resolve({
|
||||
path: to.url,
|
||||
query: to.params || {},
|
||||
});
|
||||
url = window.location.origin + (import.meta.env.VITE_BASE || "") + href;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
export function push(
|
||||
to,
|
||||
options = {
|
||||
useNativeParams: false,
|
||||
},
|
||||
) {
|
||||
if (window.SHIP_ENV === "SHIP_IOS" || window.SHIP_ENV === "SHIP_Android") {
|
||||
useNativePushPage({
|
||||
url: getNativeUrl(to, options),
|
||||
params: to.params || {},
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
path: to.url,
|
||||
query: to.params || {},
|
||||
});
|
||||
}
|
||||
}
|
||||
export function pop(to = {}) {
|
||||
if (window.SHIP_ENV === "SHIP_IOS" || window.SHIP_ENV === "SHIP_Android") {
|
||||
useNativePopPage({ delta: to.delta || 1, params: to.params || {} });
|
||||
} else {
|
||||
console.warn("H5环境无法携带参数");
|
||||
router.go(-(to.delta || 1));
|
||||
}
|
||||
}
|
||||
export function redirect(
|
||||
to,
|
||||
options = {
|
||||
useNativeParams: false,
|
||||
},
|
||||
) {
|
||||
if (window.SHIP_ENV === "SHIP_IOS" || window.SHIP_ENV === "SHIP_Android") {
|
||||
useNativeRedirectPage({
|
||||
url: getNativeUrl(to, options),
|
||||
params: to.params || {},
|
||||
});
|
||||
} else {
|
||||
router.replace({
|
||||
path: to.url,
|
||||
query: to.params || {},
|
||||
});
|
||||
}
|
||||
}
|
||||
export function reLaunch(
|
||||
to,
|
||||
options = {
|
||||
useNativeParams: false,
|
||||
},
|
||||
) {
|
||||
if (window.SHIP_ENV === "SHIP_IOS" || window.SHIP_ENV === "SHIP_Android") {
|
||||
useNativeReLaunchPage({
|
||||
url: getNativeUrl(to, options),
|
||||
params: to.params || {},
|
||||
});
|
||||
} else {
|
||||
console.warn("H5环境没有reLaunch,使用replace替代");
|
||||
router.replace({
|
||||
path: to.url,
|
||||
query: to.params || {},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
// 定位
|
||||
export function useNativeGetLocation(options, callback) {
|
||||
window.SHIP_NATIVE.requset(
|
||||
"getLocation",
|
||||
{ type: "gcj02", geocode: false, ...options },
|
||||
(data) => {
|
||||
callback && callback(data);
|
||||
},
|
||||
);
|
||||
}
|
||||
// 扫码
|
||||
export function useNativeScanCode(
|
||||
options = { onlyFromCamera: false },
|
||||
callback,
|
||||
) {
|
||||
window.SHIP_NATIVE.requset("scanCode", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取设备信息
|
||||
export function useNativeSystemInfo(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getSystemInfo", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取电池状态栏的高度
|
||||
export function useNativeGetStatusBarHeight(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getStatusBarHeight", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取消息推送的CID
|
||||
export function useNativePushClientId(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getPushClientId", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 拍照
|
||||
export function useNativeCamera(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("camera", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 录制视频
|
||||
export function useNativeRecordVideo(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("recordVideo", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 从相册选择图片和视频
|
||||
export function useNativeChooseMedia(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset(
|
||||
"chooseMedia",
|
||||
{ type: ["image"], count: 1, multiple: true, ...options },
|
||||
(data) => {
|
||||
callback && callback(data);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 唤起指定的摄像头
|
||||
export function useNativeActivateCamera(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset(
|
||||
"activateCamera",
|
||||
{
|
||||
camera: "front",
|
||||
interval: 3000,
|
||||
...options,
|
||||
},
|
||||
(data) => {
|
||||
callback && callback(data);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 关闭唤起指定的摄像头
|
||||
export function useNativeActivateCameraClose() {
|
||||
window.SHIP_NATIVE.requset("activateCameraClose");
|
||||
}
|
||||
|
||||
// 更改唤起指定的摄像头上面的文字
|
||||
export function useNativeActivateCameraSetMessage(options = {}) {
|
||||
window.SHIP_NATIVE.requset("activateCameraSetMessage", { ...options });
|
||||
}
|
||||
|
||||
// 获取权限,查询是否有权限
|
||||
export function useNativeGetPermission(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getPermission", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 打开浏览器
|
||||
export function useNativeOpenBrowser(options = {}) {
|
||||
window.SHIP_NATIVE.requset("openBrowser", { ...options });
|
||||
}
|
||||
|
||||
// 通过使用第三方 app 的方式预览附件文件
|
||||
export function useNativePreviewFile(options = {}) {
|
||||
window.SHIP_NATIVE.requset("previewFile", { ...options });
|
||||
}
|
||||
|
||||
// 选择文件
|
||||
export function useNativeChooseFile(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("chooseFile", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取当前网络状态
|
||||
export function useNativeGetNetworkType(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getNetworkType", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 获取app版本
|
||||
export function useNativeGetVersion(options = {}, callback) {
|
||||
window.SHIP_NATIVE.requset("getVersion", { ...options }, (data) => {
|
||||
callback && callback(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转到下一页
|
||||
export function useNativePushPage(options = {}) {
|
||||
window.SHIP_NATIVE.requset("push", { ...options });
|
||||
}
|
||||
|
||||
// 跳转到上一页
|
||||
export function useNativePopPage(options = {}) {
|
||||
window.SHIP_NATIVE.requset("pop", { delta: 1, ...options });
|
||||
}
|
||||
|
||||
// 关闭所有页面,打开新页面
|
||||
export function useNativeReLaunchPage(options = {}) {
|
||||
window.SHIP_NATIVE.requset("reLaunch", { ...options });
|
||||
}
|
||||
|
||||
// 重定向页面
|
||||
export function useNativeRedirectPage(options = {}) {
|
||||
window.SHIP_NATIVE.requset("redirect", { ...options });
|
||||
}
|
||||
// 版本更新
|
||||
export function getUpdateVersion(options = {}) {
|
||||
window.SHIP_NATIVE.requset("updateVersion", { ...options });
|
||||
}
|
||||
// 退出APP
|
||||
export function useNativeQuitApp() {
|
||||
window.SHIP_NATIVE.requset("quitApp");
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
|
@ -0,0 +1,50 @@
|
|||
<script setup>
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const props = defineProps({
|
||||
paddingBottom: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
paddingTop: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="content"
|
||||
v-if="systemInfo.batteryBarsHeight > 0"
|
||||
:style="{
|
||||
height: `calc(100vh - ${systemInfo.batteryBarsHeight}px - ${systemInfo.bottomSafeHeight}px)`,
|
||||
marginTop: systemInfo.batteryBarsHeight + 'px',
|
||||
paddingBottom: props.paddingBottom + 'px',
|
||||
paddingTop: props.paddingTop + 'px',
|
||||
}"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div
|
||||
class="content-wrap"
|
||||
:style="{
|
||||
paddingTop: props.paddingTop + 'px',
|
||||
paddingBottom: props.paddingBottom + 'px',
|
||||
}"
|
||||
v-else
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
overflow: scroll;
|
||||
}
|
||||
.content-wrap {
|
||||
height: 100vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,36 @@
|
|||
<script setup>
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
</script>
|
||||
<template>
|
||||
<div class="head_wrap">
|
||||
<div class="head">
|
||||
<div :style="{ height: systemInfo.batteryBarsHeight + 'px' }"></div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div :style="{ height: systemInfo.batteryBarsHeight + 'px' }"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.head {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
> div {
|
||||
background-color: #fff;
|
||||
}
|
||||
:deep(.van-nav-bar) {
|
||||
.van-icon {
|
||||
color: #222222;
|
||||
}
|
||||
}
|
||||
}
|
||||
.opacity_class {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,110 @@
|
|||
<script setup>
|
||||
import { push } from "@/assets/js/useCustomRouter.js";
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const viewDetails = (item) => {
|
||||
push({
|
||||
url: "/material/material_details",
|
||||
params: item,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="list">
|
||||
<div
|
||||
class="list-item"
|
||||
v-for="item in props.list"
|
||||
:key="item.id"
|
||||
@click="viewDetails(item)"
|
||||
>
|
||||
<div
|
||||
class="list-item-img"
|
||||
:style="{ backgroundImage: `url(${item.url})` }"
|
||||
></div>
|
||||
<div>
|
||||
<div class="list-item-title">{{ item.name }}</div>
|
||||
<div class="content">
|
||||
<div class="creator" v-if="item.creator">
|
||||
<img :src="item?.creator.avatar" alt="" />
|
||||
<span>{{ item?.creator.name }}</span>
|
||||
</div>
|
||||
<div class="list-item-hot">
|
||||
<van-icon name="fire" color="#FC5B5B" />
|
||||
<span>热度{{ item.hot }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.list-item {
|
||||
width: calc(50% - 18px);
|
||||
margin-right: 36px;
|
||||
margin-bottom: 56px;
|
||||
&:nth-child(even) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.list-item-img {
|
||||
width: 100%;
|
||||
height: 329px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
.list-item-title {
|
||||
width: 100%;
|
||||
font-weight: 800;
|
||||
font-size: 32px;
|
||||
color: #222222;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.creator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 53px;
|
||||
height: 53px;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
span {
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-item-hot {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,32 @@
|
|||
<script setup>
|
||||
import { pop } from "@/assets/js/useCustomRouter.js";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
leftArrow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const back = () => {
|
||||
pop();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<van-nav-bar
|
||||
:title="props.title"
|
||||
:left-arrow="props.leftArrow"
|
||||
:border="props.border"
|
||||
@click-left="back"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -0,0 +1,45 @@
|
|||
<script setup>
|
||||
import { reLaunch } from "@/assets/js/useCustomRouter.js";
|
||||
import { useRoute } from "vue-router";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const route = useRoute();
|
||||
const active = route.name;
|
||||
const onChange = (index) => {
|
||||
console.log("关闭所有页面,打开新页面");
|
||||
reLaunch({
|
||||
url: `/${index}`,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="van-tab"
|
||||
:style="{ paddingBottom: systemInfo.bottomSafeHeight + 'px' }"
|
||||
>
|
||||
<van-tabbar
|
||||
v-model="active"
|
||||
@change="onChange"
|
||||
:safe-area-inset-bottom="true"
|
||||
:fixed="false"
|
||||
:border="false"
|
||||
>
|
||||
<van-tabbar-item name="index" icon="home-o">首页</van-tabbar-item>
|
||||
<van-tabbar-item name="material" icon="apps-o">素材库</van-tabbar-item>
|
||||
<van-tabbar-item name="user" icon="manager-o">我的</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.van-tab {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,83 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
listNum: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
switchName: {
|
||||
type: String,
|
||||
default: "name",
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["onSwitch"]);
|
||||
const switchCurrent = (name, ind) => {
|
||||
emit("onSwitch", { name, ind });
|
||||
};
|
||||
const tabsNum = computed(() => {
|
||||
return props.listNum;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="tab-bars">
|
||||
<span
|
||||
v-for="(item, index) in props.list"
|
||||
:key="item.name"
|
||||
:class="{ active: props.current === index }"
|
||||
@click="switchCurrent(item[props.switchName], index)"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
<view class="line" :class="`line${props.current + 1}`"></view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$num: v-bind(tabsNum);
|
||||
.tab-bars {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
background-color: #fff;
|
||||
padding: 30px 0 50px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
span {
|
||||
width: calc(100% / 3);
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
color: #999999;
|
||||
}
|
||||
.active {
|
||||
color: #fc5b5b;
|
||||
font-size: 30px;
|
||||
}
|
||||
.line {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
width: 70px;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #fc5b5b;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
@for $i from 1 through 99 {
|
||||
$numberWidth: 100% / $num;
|
||||
$fixed: $numberWidth / 2;
|
||||
$deviation: 70px / 2;
|
||||
.line#{$i} {
|
||||
left: calc(($numberWidth * $i - $fixed - $deviation));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,19 @@
|
|||
import { createApp } from "vue";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import "@/assets/css/common.scss";
|
||||
import "normalize.css";
|
||||
import "animate.css";
|
||||
import "vant/es/toast/style";
|
||||
import "vant/es/dialog/style";
|
||||
import "vant/es/notify/style";
|
||||
import "vant/es/image-preview/style";
|
||||
import App from "./App.vue";
|
||||
import pinia from "./pinia";
|
||||
import router from "./router";
|
||||
// import vconsole from "vconsole";
|
||||
import "@/assets/js/nativeBridge.js";
|
||||
|
||||
// eslint-disable-next-line new-cap,no-new
|
||||
// new vconsole();
|
||||
|
||||
createApp(App).use(pinia).use(router).mount("#app");
|
|
@ -0,0 +1,7 @@
|
|||
import { createPinia } from "pinia";
|
||||
import piniaPersistedstate from "pinia-plugin-persistedstate";
|
||||
|
||||
const pinia = createPinia();
|
||||
pinia.use(piniaPersistedstate);
|
||||
|
||||
export default pinia;
|
|
@ -0,0 +1,19 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const useMiscellaneousStore = defineStore("miscellaneousStore", {
|
||||
state: () => ({
|
||||
loading: false, // 全局加载动画
|
||||
}),
|
||||
getters: {
|
||||
getLoading: (state) => state.loading,
|
||||
},
|
||||
actions: {
|
||||
setLoading(loading) {
|
||||
this.loading = loading;
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
storage: window.sessionStorage,
|
||||
paths: ["loading"],
|
||||
},
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const systemInfoStore = defineStore("systemInfoStore", {
|
||||
state: () => ({
|
||||
systemInfo: {
|
||||
batteryBarsHeight: 0,
|
||||
bottomSafeHeight: 0,
|
||||
system: {},
|
||||
address: {},
|
||||
},
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setSystemInfo(data, name) {
|
||||
this.systemInfo[name] = data;
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
storage: window.sessionStorage,
|
||||
paths: ["systemInfo"],
|
||||
},
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const useUserStore = defineStore("useUserStore", {
|
||||
state: () => ({
|
||||
data: {
|
||||
userInfo: {},
|
||||
release: [],
|
||||
},
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setUserData(data, name) {
|
||||
if (name === "release") {
|
||||
this.data[name].push(data);
|
||||
return;
|
||||
}
|
||||
this.data[name] = data;
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
storage: window.localStorage,
|
||||
paths: ["data"],
|
||||
},
|
||||
});
|
|
@ -0,0 +1,239 @@
|
|||
import { defineStore } from "pinia";
|
||||
import avatar5 from "@/assets/images/avatar5.jpg";
|
||||
import avatar2 from "@/assets/images/avatar2.jpg";
|
||||
import avatar3 from "@/assets/images/avatar3.jpg";
|
||||
import avatar4 from "@/assets/images/avatar4.jpg";
|
||||
import avatar1 from "@/assets/images/avatar1.jpg";
|
||||
import avatar6 from "@/assets/images/avatar6.jpg";
|
||||
|
||||
export const useWorksStore = defineStore("useWorksStore", {
|
||||
state: () => ({
|
||||
data: {
|
||||
release: [
|
||||
{
|
||||
id: 1,
|
||||
url: "https://fastly.picsum.photos/id/866/200/300.jpg?hmac=rcadCENKh4rD6MAp6V_ma-AyWv641M4iiOpe1RyFHeI",
|
||||
name: "九寨沟风景",
|
||||
hot: 1354,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
url: "https://fastly.picsum.photos/id/62/300/300.jpg?hmac=JkaOmZr8So-hvPO3Mya00sE2pvIQtLZjGMldqbPFiqc",
|
||||
name: "风景",
|
||||
hot: 896,
|
||||
classify: "2",
|
||||
type: "2",
|
||||
creator: {
|
||||
name: "风景一线",
|
||||
avatar: avatar5,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
url: "https://fastly.picsum.photos/id/858/300/300.jpg?hmac=_ejZ2a4fSroS4BO_gXXIxq7hyd0RIHSP290jgbqMO2c",
|
||||
name: "都市风格",
|
||||
hot: 27,
|
||||
classify: "2",
|
||||
type: "3",
|
||||
creator: {
|
||||
name: "Ammy",
|
||||
avatar: avatar2,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
url: "https://fastly.picsum.photos/id/472/300/300.jpg?hmac=a3XXSq9tQnozNx-l8rmPt0Y-orMbCaE2t8lMdPeyl8I",
|
||||
name: "云雾",
|
||||
hot: 447,
|
||||
classify: "2",
|
||||
type: "2",
|
||||
creator: {
|
||||
name: "风景一线",
|
||||
avatar: avatar5,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
url: "https://fastly.picsum.photos/id/72/300/300.jpg?hmac=tx7xDri-jWJWeXKZ4OwXuD9jCiWOgGtfZBNC11VAX8g",
|
||||
name: "黑白",
|
||||
hot: 8446,
|
||||
classify: "1",
|
||||
type: "3",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
url: "https://fastly.picsum.photos/id/423/300/300.jpg?hmac=b-ZC4rgdo_5hNS1yFs9pkVkPN7Co7dJ8TBAGFCPhYCs",
|
||||
name: "雪松",
|
||||
hot: 21,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
url: "https://fastly.picsum.photos/id/730/300/300.jpg?hmac=-ZzQFNagVnAQRxKCAdznDnNils2eMzvfT7ooODMz1ws",
|
||||
name: "雪中的景色",
|
||||
hot: 12,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
url: "https://fastly.picsum.photos/id/299/300/300.jpg?hmac=AL30gVrvEQMZgWvQ53mFxMB2rRy8wNO9yDOHwEsO1k0",
|
||||
name: "街道",
|
||||
hot: 93,
|
||||
classify: "2",
|
||||
type: "1",
|
||||
creator: {
|
||||
name: "雾迷了风景",
|
||||
avatar: avatar3,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
url: "https://fastly.picsum.photos/id/808/300/300.jpg?hmac=ezNKdtmIxkOpancGBAvNd5QiBskqPBhhHN1jV9IvP0I",
|
||||
name: "田地",
|
||||
hot: 123,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
url: "https://fastly.picsum.photos/id/866/400/300.jpg?hmac=JMubLT0llOloTrCSJIptm4kmT13cmWrNcdbpI9vJwmw",
|
||||
name: "雪中山峰",
|
||||
hot: 53,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
url: "https://fastly.picsum.photos/id/461/400/300.jpg?hmac=LxC9-n5d-4ruUfj2z_sK-A1bvOrkDiWtG_V2umD0c7U",
|
||||
name: "海边",
|
||||
hot: 45,
|
||||
classify: "1",
|
||||
type: "2",
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
url: "https://fastly.picsum.photos/id/818/400/300.jpg?hmac=bmrMnmW7AtSXUVO7K5b8F4BHfX2_CSO8VR7xzjlACPo",
|
||||
name: "自由女神像",
|
||||
hot: 456,
|
||||
classify: "1",
|
||||
type: "1",
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
url: "https://fastly.picsum.photos/id/369/300/400.jpg?hmac=GTBdppLn_1mhzd23S7owmFFdI4eGewmZQB6lrPLd8lI",
|
||||
name: "街道",
|
||||
hot: 453,
|
||||
classify: "1",
|
||||
type: "1",
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
url: "https://fastly.picsum.photos/id/408/300/400.jpg?hmac=1pTfKCG8_tiCVSoQSOYZ8zlKnh2jBmhZWpf3zy9X0hc",
|
||||
name: "城市",
|
||||
hot: 456,
|
||||
classify: "2",
|
||||
type: "1",
|
||||
creator: {
|
||||
name: "是风景",
|
||||
avatar: avatar4,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
url: "https://fastly.picsum.photos/id/884/400/300.jpg?hmac=1RfUNtqPHogkhXDXPCPKjTfiNfJ_KHjx-Td_J4K8P4Q",
|
||||
name: "沙漠的夜空",
|
||||
hot: 45,
|
||||
classify: "2",
|
||||
type: "2",
|
||||
creator: {
|
||||
name: "Rumi",
|
||||
avatar: avatar1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
url: "https://fastly.picsum.photos/id/480/300/400.jpg?hmac=TH4P4XKNsw19R2bhQAEKxMnsRSFvQPG7CTb6Jt3wbcQ",
|
||||
name: "田野",
|
||||
hot: 86,
|
||||
classify: "2",
|
||||
type: "2",
|
||||
creator: {
|
||||
name: "Rumi",
|
||||
avatar: avatar1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
url: "https://fastly.picsum.photos/id/220/300/400.jpg?hmac=-37QrITtobNkaprlkFaWKkc4-plr-KZJu68_nM2jnBI",
|
||||
name: "夜晚车站",
|
||||
hot: 4556,
|
||||
classify: "1",
|
||||
type: "1",
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
url: "https://fastly.picsum.photos/id/241/300/400.jpg?hmac=73lq2CQa3NiMAdFOA6xPdkbwPqL6ru_koaZjarmjtoY",
|
||||
name: "老照片",
|
||||
hot: 452,
|
||||
classify: "2",
|
||||
type: "3",
|
||||
creator: {
|
||||
name: "旅途Φの风景",
|
||||
avatar: avatar6,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
url: "https://fastly.picsum.photos/id/679/300/300.jpg?hmac=sOnn1erXgFUtrEBHqNgADZqc_mVDj-eKoCtg3Rb5qmM",
|
||||
name: "螺旋",
|
||||
hot: 981,
|
||||
classify: "2",
|
||||
type: "3",
|
||||
creator: {
|
||||
name: "旅途Φの风景",
|
||||
avatar: avatar6,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
url: "https://fastly.picsum.photos/id/43/200/300.jpg?hmac=F_cVhLISpNmZ9wjirHfMJgX9rQzMYJbJE1xzfwmV36c",
|
||||
name: "夜景",
|
||||
hot: 8446,
|
||||
classify: "2",
|
||||
type: "3",
|
||||
creator: {
|
||||
name: "Rumi",
|
||||
avatar: avatar1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setShield(data, name) {
|
||||
if (name === "works") {
|
||||
this.data.release = this.data.release.filter(
|
||||
(item) => item.id !== Number(data.id),
|
||||
);
|
||||
return;
|
||||
}
|
||||
const newItem = this.data.release.filter(
|
||||
(item) => item.id === Number(data.id),
|
||||
);
|
||||
const list = this.data.release.filter((item) => item.classify === "2");
|
||||
|
||||
this.data.release = list.filter(
|
||||
(item) => item.creator.name !== newItem[0].creator.name,
|
||||
);
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
storage: window.localStorage,
|
||||
paths: ["data"],
|
||||
},
|
||||
});
|
|
@ -0,0 +1,140 @@
|
|||
import axios from "axios";
|
||||
import router from "../router";
|
||||
import QS from "qs";
|
||||
import { showToast } from "vant";
|
||||
import { useMiscellaneousStore } from "../pinia/miscellaneous";
|
||||
|
||||
const miscellaneousStore = useMiscellaneousStore();
|
||||
|
||||
function startLoading() {
|
||||
miscellaneousStore.setLoading(true);
|
||||
}
|
||||
|
||||
function endLoading() {
|
||||
miscellaneousStore.setLoading(false);
|
||||
}
|
||||
|
||||
axios.defaults.timeout = 1000 * 60 * 10;
|
||||
// axios.defaults.withCredentials = true;
|
||||
axios.interceptors.request.use(
|
||||
(config) => {
|
||||
if (config.method === "get" || config.method === "GET") {
|
||||
if (QS.parse(config.params)?.loading !== "false") startLoading();
|
||||
}
|
||||
if (config.method === "post" || config.method === "POST") {
|
||||
if (QS.parse(config.data)?.loading !== "false") startLoading();
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => Promise.reject(error)
|
||||
);
|
||||
|
||||
axios.interceptors.response.use(
|
||||
(config) => {
|
||||
if (config.config.method === "get" || config.config.method === "GET") {
|
||||
if (QS.parse(config.config.params)?.loading !== "false") endLoading();
|
||||
}
|
||||
if (config.config.method === "post" || config.config.method === "POST") {
|
||||
if (QS.parse(config.config.data)?.loading !== "false") endLoading();
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
if (error && error.response) {
|
||||
switch (error.response.status) {
|
||||
case 0:
|
||||
case 302:
|
||||
endLoading();
|
||||
showToast("登录失效,请重新登陆");
|
||||
router.push("/login").then();
|
||||
break;
|
||||
case 401:
|
||||
endLoading();
|
||||
router.push("/login").then();
|
||||
break;
|
||||
default:
|
||||
error.message = `连接错误${error.response.status}`;
|
||||
showToast(`连接错误${error.response.status}`);
|
||||
}
|
||||
} else {
|
||||
error.message = "连接到服务器失败";
|
||||
showToast("连接到服务器失败");
|
||||
}
|
||||
return Promise.reject(error.message);
|
||||
}
|
||||
);
|
||||
|
||||
export function post(url, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post(
|
||||
url,
|
||||
QS.stringify({
|
||||
...params,
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.data.result === "success" && res.data.code !== "9999") {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
showToast(res.data.msg || "系统开小差了");
|
||||
reject(res.data);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function get(url, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get(url, {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
params: QS.stringify({
|
||||
...params,
|
||||
}),
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data.result === "success" && res.data.code !== "9999") {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
showToast(res.data.msg || "系统开小差了");
|
||||
reject(res.data);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function upload(url, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post(url, params, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data.result === "success" && res.data.code !== "9999") {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
showToast(res.data.msg || "系统开小差了");
|
||||
reject(res.data);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
|
||||
const routes = [
|
||||
{ path: "/", redirect: "/index" },
|
||||
{
|
||||
path: "/index",
|
||||
name: "index",
|
||||
meta: { title: "首页", navbar: false },
|
||||
component: () => import("@/views/index/index"),
|
||||
},
|
||||
{
|
||||
path: "/platform",
|
||||
name: "platform",
|
||||
meta: { title: "平台素材", navbar: false },
|
||||
component: () => import("@/views/platform/platform"),
|
||||
},
|
||||
{
|
||||
path: "/expert",
|
||||
name: "expert",
|
||||
meta: { title: "达人分享", navbar: false },
|
||||
component: () => import("@/views/expert/expert"),
|
||||
},
|
||||
{
|
||||
path: "/login",
|
||||
name: "login",
|
||||
meta: { title: "登录", navbar: false },
|
||||
component: () => import("@/views/login/login"),
|
||||
},
|
||||
{
|
||||
path: "/change_password",
|
||||
name: "change_password",
|
||||
meta: { title: "修改密码", navbar: false },
|
||||
component: () => import("@/views/change_password/change_password"),
|
||||
},
|
||||
{
|
||||
path: "/material",
|
||||
name: "material",
|
||||
meta: { title: "素材列表", navbar: false },
|
||||
component: () => import("@/views/material/material"),
|
||||
},
|
||||
{
|
||||
path: "/material/material_details",
|
||||
name: "material_details",
|
||||
meta: { title: "素材详情", navbar: false },
|
||||
component: () => import("@/views/material_details/material_details"),
|
||||
},
|
||||
{
|
||||
path: "/my_upload",
|
||||
name: "my_upload",
|
||||
meta: { title: "我要上传", navbar: false },
|
||||
component: () => import("@/views/my_upload/my_upload"),
|
||||
},
|
||||
{
|
||||
path: "/user",
|
||||
name: "user",
|
||||
meta: { title: "个人中心", navbar: false },
|
||||
component: () => import("@/views/user/user"),
|
||||
},
|
||||
{
|
||||
path: "/user/problem_feedback",
|
||||
name: "problem_feedback",
|
||||
meta: { title: "问题反馈", navbar: false },
|
||||
component: () => import("@/views/problem_feedback/problem_feedback"),
|
||||
},
|
||||
{
|
||||
path: "/user/privacy_agreement",
|
||||
name: "privacy_agreement",
|
||||
meta: { title: "隐私协议", navbar: false },
|
||||
component: () => import("@/views/privacy_agreement/privacy_agreement"),
|
||||
},
|
||||
{
|
||||
path: "/user/user_agreement",
|
||||
name: "user_agreement",
|
||||
meta: { title: "用户协议", navbar: false },
|
||||
component: () => import("@/views/user_agreement/user_agreement"),
|
||||
},
|
||||
{
|
||||
path: "/user/my_release",
|
||||
name: "my_release",
|
||||
meta: { title: "我的发布", navbar: false },
|
||||
component: () => import("@/views/my_release/my_release"),
|
||||
},
|
||||
{
|
||||
path: "/search",
|
||||
name: "search",
|
||||
meta: { title: "搜索", navbar: false },
|
||||
component: () => import("@/views/search/search"),
|
||||
},
|
||||
{
|
||||
path: "/search/search_list",
|
||||
name: "search_list",
|
||||
meta: { title: "搜索结果", navbar: false },
|
||||
component: () => import("@/views/search_list/search_list"),
|
||||
},
|
||||
{
|
||||
path: "/cancel_account",
|
||||
name: "cancel_account",
|
||||
meta: { title: "申请注销账号", navbar: false },
|
||||
component: () => import("@/views/cancel_account/cancel_account"),
|
||||
},
|
||||
];
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(import.meta.env.BASE_URL),
|
||||
routes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition;
|
||||
} else {
|
||||
return { left: 0, top: 0 };
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default router;
|
|
@ -0,0 +1,67 @@
|
|||
<script setup>
|
||||
import { showDialog } from "vant";
|
||||
import { reLaunch } from "@/assets/js/useCustomRouter.js";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
|
||||
const onCancel = () => {
|
||||
showDialog({
|
||||
title: "提示",
|
||||
message: "我们将在7-15工作日处理",
|
||||
confirmButtonText: "确认注销",
|
||||
showCancelButton: true,
|
||||
})
|
||||
.then(() => {
|
||||
reLaunch({
|
||||
url: "/login",
|
||||
params: {},
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(222);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="申请注销账号" :left-arrow="true" :border="false"></nav-bar>
|
||||
</tab-header>
|
||||
<p class="title">
|
||||
为保证你的账号安全,在你提交的注销申请生效前,需同时满足以下条件:
|
||||
</p>
|
||||
<p>1.账号处于安全状态</p>
|
||||
<span>账号为你本人拥有,处于正常使用状态,无被盗、违规、封禁风险。</span>
|
||||
<p>2.账号财产已结清,交易已完成</p>
|
||||
<span
|
||||
>账号下所有关联业务和权益均已清空或自愿放弃,所有上传作品已删除或已自愿放弃。
|
||||
账号对应的信息将同步注销。</span
|
||||
>
|
||||
<p>3.账号无任何纠纷,包括但不限于投诉或举报,服务均已完成或已自愿放弃</p>
|
||||
<van-button class="button" color="#fe5353" @click="onCancel">下一步</van-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
padding: 20px 30px;
|
||||
.title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 15px;
|
||||
font-size: 30px;
|
||||
line-height: 50px;
|
||||
}
|
||||
span {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.button {
|
||||
position: fixed;
|
||||
left: 20px;
|
||||
bottom: 30px;
|
||||
right: 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,173 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { showToast } from "vant";
|
||||
import { push } from "@/assets/js/useCustomRouter.js";
|
||||
import logo from "@/assets/images/logo.png";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const loginData = ref({
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
oldPassword: "",
|
||||
});
|
||||
|
||||
const login = () => {
|
||||
if (!valida()) return;
|
||||
push({
|
||||
url: "/login",
|
||||
param: {},
|
||||
});
|
||||
};
|
||||
const valida = () => {
|
||||
if (loginData.value.oldPassword === "") {
|
||||
showToast("请输入旧密码");
|
||||
return false;
|
||||
}
|
||||
if (loginData.value.password === "") {
|
||||
showToast("请输入密码");
|
||||
return false;
|
||||
}
|
||||
if (loginData.value.confirmPassword === "") {
|
||||
showToast("请再次输入密码");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login">
|
||||
<div
|
||||
class="head"
|
||||
:style="{ paddingTop: systemInfo.batteryBarsHeight + 'px' }"
|
||||
>
|
||||
<nav-bar title="修改密码" :left-arrow="true" :border="false"></nav-bar>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="logo">
|
||||
<img :src="logo" alt="" />
|
||||
</div>
|
||||
<div class="title">校园安全一点通</div>
|
||||
</div>
|
||||
<div class="login-form">
|
||||
<div class="form-item">
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginData.oldPassword"
|
||||
placeholder="请输入旧密码"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginData.password"
|
||||
placeholder="请输入新密码"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginData.confirmPassword"
|
||||
placeholder="再次输入新密码"
|
||||
/>
|
||||
</div>
|
||||
<button class="submit" @click="login">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.head {
|
||||
:deep(.van-nav-bar) {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
.van-nav-bar__title {
|
||||
color: #222222;
|
||||
}
|
||||
.van-icon {
|
||||
color: #222222;
|
||||
}
|
||||
}
|
||||
}
|
||||
.login {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-image: url("../../assets/images/login_bj.jpg");
|
||||
background-size: cover;
|
||||
background-position: top center;
|
||||
}
|
||||
.box {
|
||||
padding-top: 124px;
|
||||
.logo {
|
||||
width: 116px;
|
||||
height: 116px;
|
||||
padding: 21px;
|
||||
margin: 0 auto 36px;
|
||||
border-radius: 17px;
|
||||
background-color: #fff;
|
||||
img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 38px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 34px;
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
margin-bottom: 96px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
color: #4f4e4e;
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
.login-form {
|
||||
border-radius: 67px 67px 0 0;
|
||||
background-color: #fff;
|
||||
flex: 1;
|
||||
padding: 121px 92px 0;
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 99px;
|
||||
background-color: #f6f9ff;
|
||||
border-radius: 50px;
|
||||
margin-bottom: 75px;
|
||||
padding: 0 32px 0 59px;
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
span {
|
||||
width: 145px;
|
||||
display: block;
|
||||
font-size: 27px;
|
||||
color: #fe5353;
|
||||
}
|
||||
}
|
||||
.submit {
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 99px;
|
||||
background-color: #fe5353;
|
||||
border-radius: 50px;
|
||||
border: 1px solid #fe5353;
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,55 @@
|
|||
<script setup>
|
||||
import {computed, ref} from "vue";
|
||||
import IndexList from "@/components/index-list/index-list.vue";
|
||||
import Tabs from "@/components/tabs/tabs.vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const worksStore = useWorksStore();
|
||||
const { data } = storeToRefs(worksStore);
|
||||
const navList = [
|
||||
{ name: "都市风格", id: "1" },
|
||||
{ name: "唯美风景", id: "2" },
|
||||
{ name: "黑白照片", id: "3" },
|
||||
];
|
||||
const hotList = computed(() => {
|
||||
return data.value.release.filter((item) => item.classify === "2");
|
||||
});
|
||||
const list = ref([]);
|
||||
const current = ref(0);
|
||||
const switchCurrent = (option) => {
|
||||
current.value = option.ind;
|
||||
list.value = hotList.value.filter((item) => item.type === option.name);
|
||||
};
|
||||
switchCurrent({ ind: 0, name: "1" });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="达人分享" :left-arrow="true" :border="false"></nav-bar>
|
||||
<tabs
|
||||
:current="current"
|
||||
:list-num="3"
|
||||
switch-name="id"
|
||||
:list="navList"
|
||||
@on-switch="switchCurrent"
|
||||
></tabs>
|
||||
</tab-header>
|
||||
<content :padding-top="110">
|
||||
<div class="list-box">
|
||||
<index-list :list="list"></index-list>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list-box {
|
||||
padding: 0 26px 55px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,239 @@
|
|||
<template>
|
||||
<div
|
||||
class="wrap"
|
||||
:style="{ height: `calc(100vh - ${systemInfo.bottomSafeHeight} + px)` }"
|
||||
>
|
||||
<div class="head">
|
||||
<div class="head-nav">
|
||||
<span>校园安全一点通</span>
|
||||
<van-icon
|
||||
name="scan"
|
||||
size="22px"
|
||||
@click="fnScanCode({ onlyFromCamera: true })"
|
||||
/>
|
||||
</div>
|
||||
<span>好评如潮的素材平台,3,960,000+内容等你发现</span>
|
||||
<div class="search" @click="jump({ url: '/search', param: {} })">
|
||||
<input type="text" readonly placeholder="搜索爆款短视频或文案教材" />
|
||||
<van-icon name="search" size="20px" />
|
||||
</div>
|
||||
<div class="nav-list">
|
||||
<div
|
||||
class="nav-list-item"
|
||||
v-for="item in navList"
|
||||
:key="item.name"
|
||||
@click="jump(item.page)"
|
||||
>
|
||||
<img :src="item.url" alt="" />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="banner">
|
||||
<img
|
||||
:src="item.url"
|
||||
alt=""
|
||||
v-for="item in bannerList"
|
||||
:key="item.id"
|
||||
@click="jump(item.page)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-box">
|
||||
<div class="list-box-title">
|
||||
<span>平台作品</span>
|
||||
<div class="more" @click="more(1)">
|
||||
<span>更多</span>
|
||||
<van-icon name="arrow" size="14px" color="#999999" />
|
||||
</div>
|
||||
</div>
|
||||
<index-list :list="hotList"></index-list>
|
||||
</div>
|
||||
<div class="list-box">
|
||||
<div class="list-box-title">
|
||||
<span>达人分享</span>
|
||||
<div class="more" @click="more(2)">
|
||||
<span>更多</span>
|
||||
<van-icon name="arrow" size="14px" color="#999999" />
|
||||
</div>
|
||||
</div>
|
||||
<index-list :list="expert"></index-list>
|
||||
</div>
|
||||
</div>
|
||||
<tabbar select-tab="index"></tabbar>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { push, reLaunch } from "@/assets/js/useCustomRouter.js";
|
||||
import { useNativeScanCode } from "@/assets/js/useNative.js";
|
||||
import nav1 from "@/assets/images/nav_1.png";
|
||||
import nav2 from "@/assets/images/nav_2.png";
|
||||
import nav3 from "@/assets/images/nav_3.png";
|
||||
import banner1 from "@/assets/images/banner_1.png";
|
||||
import banner2 from "@/assets/images/banner_2.png";
|
||||
import IndexList from "@/components/index-list/index-list";
|
||||
import Tabbar from "@/components/tabbar/tabbar.vue";
|
||||
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
const userStore = useUserStore();
|
||||
const { data } = storeToRefs(userStore);
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const worksStore = useWorksStore();
|
||||
const { data: worksData } = storeToRefs(worksStore);
|
||||
|
||||
const navList = [
|
||||
{
|
||||
name: "平台作品",
|
||||
url: nav1,
|
||||
page: { url: "/platform", params: {} },
|
||||
},
|
||||
{
|
||||
name: "达人分享",
|
||||
url: nav2,
|
||||
page: { url: "/expert", params: {} },
|
||||
},
|
||||
{
|
||||
name: "我要上传",
|
||||
url: nav3,
|
||||
page: { url: "/my_upload", params: {} },
|
||||
},
|
||||
];
|
||||
const bannerList = [
|
||||
{ id: 1, url: banner1, page: { url: "/material", params: {} } },
|
||||
{ id: 2, url: banner2, page: { url: "/my_upload", params: {} } },
|
||||
];
|
||||
const scanCode = ref("");
|
||||
const hotList = computed(() => {
|
||||
const list = worksData.value.release.filter((item) => item.classify === "1");
|
||||
return list.splice(0, 5);
|
||||
});
|
||||
const expert = computed(() => {
|
||||
const list = worksData.value.release.filter((item) => item.classify === "2");
|
||||
return list.splice(0, 5);
|
||||
});
|
||||
if (!data.value.userInfo.userName) {
|
||||
reLaunch({
|
||||
url: "/login",
|
||||
});
|
||||
}
|
||||
const fnScanCode = (options) => {
|
||||
useNativeScanCode(options, (data) => {
|
||||
scanCode.value = data;
|
||||
console.log(scanCode.value, "二维码");
|
||||
});
|
||||
};
|
||||
const more = (type) => {
|
||||
push({
|
||||
url: "/material",
|
||||
params: {
|
||||
pageType: type,
|
||||
},
|
||||
});
|
||||
};
|
||||
const jump = (options) => {
|
||||
push(options);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrap {
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
padding-bottom: 96px;
|
||||
}
|
||||
.head {
|
||||
padding: 120px 32px 24px 28px;
|
||||
background-image: url("../../assets/images/login_bj.jpg");
|
||||
background-size: cover;
|
||||
background-position: top center;
|
||||
> span {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
color: #222222;
|
||||
margin: 24px 0;
|
||||
}
|
||||
.head-nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span {
|
||||
font-weight: 800;
|
||||
font-size: 40px;
|
||||
color: #222222;
|
||||
}
|
||||
}
|
||||
.search {
|
||||
height: 88px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 44px;
|
||||
border: 1px solid #ececec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 36px 0 30px;
|
||||
input {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
}
|
||||
}
|
||||
.nav-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 36px 0;
|
||||
.nav-list-item {
|
||||
width: calc(100% / 4);
|
||||
img {
|
||||
width: 100px;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
span {
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
color: #222222;
|
||||
line-height: 60px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.banner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
img {
|
||||
width: calc(50% - 14px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-box {
|
||||
border-top: 14px solid #f3f3f3;
|
||||
padding: 30px 26px 0;
|
||||
.list-box-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 45px;
|
||||
> span {
|
||||
font-weight: 800;
|
||||
font-size: 32px;
|
||||
color: #222222;
|
||||
line-height: 48px;
|
||||
}
|
||||
.more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span {
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,202 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { showToast } from "vant";
|
||||
import { push } from "@/assets/js/useCustomRouter.js";
|
||||
import logo from "@/assets/images/logo.png";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
const userStore = useUserStore();
|
||||
const loginData = ref({
|
||||
userName: "",
|
||||
password: "",
|
||||
});
|
||||
const checked = ref(false);
|
||||
const login = () => {
|
||||
if (!valida()) return;
|
||||
push({
|
||||
url: "/index",
|
||||
param: {},
|
||||
});
|
||||
userStore.setUserData(loginData.value, "userInfo");
|
||||
};
|
||||
|
||||
const valida = () => {
|
||||
if (!checked.value) {
|
||||
showToast("请先同意用户协议");
|
||||
return false;
|
||||
}
|
||||
const merge =
|
||||
/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[0-9])\d{8}$/;
|
||||
if (loginData.value.userName === "") {
|
||||
showToast("请输入手机号");
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
loginData.value.userName.length !== 11 ||
|
||||
!merge.test(loginData.value.userName)
|
||||
) {
|
||||
showToast("手机号格式不正确");
|
||||
return false;
|
||||
}
|
||||
if (loginData.value.password === "") {
|
||||
showToast("请输入密码");
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
loginData.value.userName !== "18700000000" &&
|
||||
loginData.value.password !== "123456"
|
||||
) {
|
||||
showToast("用户名密码不正确");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const onAgreement = (type) => {
|
||||
if (type === "user") {
|
||||
push({ url: "/user/user_agreement", params: {} });
|
||||
} else {
|
||||
push({ url: "/user/privacy_agreement", params: {} });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login">
|
||||
<div class="box">
|
||||
<div class="logo">
|
||||
<img :src="logo" alt="" />
|
||||
</div>
|
||||
<div class="title">校园安全一点通</div>
|
||||
<span>未注册手机号将自动注册并登录</span>
|
||||
</div>
|
||||
<div class="login-form">
|
||||
<div class="form-item mb75">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginData.userName"
|
||||
placeholder="请输入手机号"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item mb50">
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginData.password"
|
||||
placeholder="请输入新密码"
|
||||
/>
|
||||
</div>
|
||||
<div class="agreement mb50">
|
||||
<van-checkbox v-model="checked" checked-color="#fe5353"></van-checkbox>
|
||||
<p>
|
||||
我已阅读并同意<span @click="onAgreement('user')">《用户协议》</span
|
||||
>和<span @click="onAgreement('privacy')">《隐私条款》</span>
|
||||
</p>
|
||||
</div>
|
||||
<button class="submit" @click="login">登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
background-image: url("../../assets/images/login_bj.jpg");
|
||||
background-size: cover;
|
||||
background-position: top center;
|
||||
padding-bottom: 60px;
|
||||
overflow: auto;
|
||||
}
|
||||
.box {
|
||||
padding-top: 224px;
|
||||
.logo {
|
||||
width: 116px;
|
||||
height: 116px;
|
||||
padding: 21px;
|
||||
margin: 0 auto 36px;
|
||||
border-radius: 17px;
|
||||
background-color: #fff;
|
||||
img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 38px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 34px;
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
margin-bottom: 96px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
color: #4f4e4e;
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
.login-form {
|
||||
border-radius: 67px 67px 0 0;
|
||||
background-color: #fff;
|
||||
//flex: 1;
|
||||
padding: 121px 92px 100px;
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 99px;
|
||||
background-color: #f6f9ff;
|
||||
border-radius: 50px;
|
||||
padding: 0 32px 0 59px;
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
font-size: 24px;
|
||||
}
|
||||
span {
|
||||
width: 135px;
|
||||
display: block;
|
||||
font-size: 27px;
|
||||
color: #fe5353;
|
||||
}
|
||||
:deep {
|
||||
.van-checkbox__icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mb50 {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
.mb75 {
|
||||
margin-bottom: 75px;
|
||||
}
|
||||
.agreement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
p {
|
||||
font-size: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
span {
|
||||
color: #fe5353;
|
||||
}
|
||||
}
|
||||
.submit {
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 99px;
|
||||
background-color: #fe5353;
|
||||
border-radius: 50px;
|
||||
border: 1px solid #fe5353;
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,64 @@
|
|||
<script setup>
|
||||
import {computed, ref} from "vue";
|
||||
import IndexList from "@/components/index-list/index-list.vue";
|
||||
import Tabbar from "@/components/tabbar/tabbar.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Tabs from "@/components/tabs/tabs.vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import Content from "@/components/content/content.vue";
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const worksStore = useWorksStore();
|
||||
const { data } = storeToRefs(worksStore);
|
||||
const route = useRoute();
|
||||
const pageType = route.query.pageType || "1";
|
||||
const navList = [
|
||||
{ name: "平台素材", id: "1" },
|
||||
{ name: "达人分享", id: "2" },
|
||||
];
|
||||
const list = ref([]);
|
||||
const current = ref(1);
|
||||
const hotList = computed(() => {
|
||||
return data.value.release;
|
||||
});
|
||||
const switchCurrent = (option) => {
|
||||
current.value = option.ind;
|
||||
list.value = hotList.value.filter((item) => item.classify === option.name);
|
||||
};
|
||||
window.initData = (data) => {
|
||||
console.log(data, "获取参数");
|
||||
};
|
||||
switchCurrent({ ind: pageType - 1, name: pageType });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar
|
||||
title="素材库"
|
||||
:left-arrow="!!route.query.pageType"
|
||||
:border="false"
|
||||
></nav-bar>
|
||||
<tabs
|
||||
:current="current"
|
||||
:list-num="3"
|
||||
switch-name="id"
|
||||
:list="navList"
|
||||
@on-switch="switchCurrent"
|
||||
></tabs>
|
||||
</tab-header>
|
||||
<content :padding-bottom="98" :padding-top="110">
|
||||
<div class="list-box">
|
||||
<index-list :list="list"></index-list>
|
||||
</div>
|
||||
</content>
|
||||
<tabbar select-tab="material"></tabbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list-box {
|
||||
padding: 0 26px 55px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,173 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { pop } from "@/assets/js/useCustomRouter.js";
|
||||
import { useRoute } from "vue-router";
|
||||
import { showDialog, showToast } from "vant";
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const worksStore = useWorksStore();
|
||||
// import { useNativePreviewFile } from "@/assets/js/useNative.js";
|
||||
const route = useRoute();
|
||||
const details = route.query;
|
||||
const show = ref(false);
|
||||
const message = ref("");
|
||||
const back = () => {
|
||||
pop();
|
||||
};
|
||||
// const open = () => {
|
||||
// useNativePreviewFile({
|
||||
// url: "https://jpfz.qhdsafety.com/demo/%E9%99%84%E4%BB%B6.doc",
|
||||
// });
|
||||
// };
|
||||
const onSubmit = () => {
|
||||
if (!message.value) {
|
||||
showToast("请输入举报信息");
|
||||
return false;
|
||||
}
|
||||
message.value = "";
|
||||
show.value = false;
|
||||
showDialog({
|
||||
title: "提示",
|
||||
message: "举报成功,我们将在7-15工作日处理",
|
||||
confirmButtonText: "确认",
|
||||
});
|
||||
};
|
||||
const shield = (type) => {
|
||||
const msg = type === "author" ? "作者" : "作品";
|
||||
showDialog({
|
||||
title: "提示",
|
||||
message: `是否屏蔽该${msg}?`,
|
||||
confirmButtonText: "确认屏蔽",
|
||||
showCancelButton: true,
|
||||
})
|
||||
.then(() => {
|
||||
worksStore.setShield(details, type);
|
||||
back();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<img :src="details.url" alt="" />
|
||||
<div class="details-content">
|
||||
<div class="title">
|
||||
{{ details.name }}
|
||||
</div>
|
||||
<div class="back" :style="{ top: systemInfo.batteryBarsHeight + 'px' }">
|
||||
<van-button class="ml-5" size="small" color="red" @click="show = true"
|
||||
>举报</van-button
|
||||
>
|
||||
<van-button
|
||||
v-if="details.classify === '2'"
|
||||
class="ml-5"
|
||||
size="small"
|
||||
color=""
|
||||
@click="shield('author')"
|
||||
>屏蔽作者</van-button
|
||||
>
|
||||
<van-button class="ml-5" size="small" color="" @click="shield('works')"
|
||||
>屏蔽作品</van-button
|
||||
>
|
||||
<div class="nav-style" @click="back">
|
||||
<van-icon name="cross" color="#fff" size="20px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-popup v-model:show="show" round>
|
||||
<div class="report">
|
||||
<div class="title">举报</div>
|
||||
<div class="report_input">
|
||||
<van-field
|
||||
v-model="message"
|
||||
:border="true"
|
||||
rows="1"
|
||||
autosize
|
||||
type="textarea"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<van-button size="small" @click="show = false">取消</van-button>
|
||||
<van-button size="small" color="#fe5353" @click="onSubmit"
|
||||
>提交</van-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
height: 100vh;
|
||||
background-color: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
> img {
|
||||
width: 100%;
|
||||
}
|
||||
.details-content {
|
||||
position: fixed;
|
||||
padding: 20px 36px 100px;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
.title {
|
||||
font-size: 26px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
}
|
||||
.nav-style {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
background-color: #262626;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.back {
|
||||
position: fixed;
|
||||
right: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.report {
|
||||
width: 600px;
|
||||
padding: 45px;
|
||||
border-radius: 10px;
|
||||
.title {
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.report_input {
|
||||
border: 1px solid #dedede;
|
||||
}
|
||||
.btn {
|
||||
margin-top: 45px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
button {
|
||||
width: calc(50% - 10px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.ml-5 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,52 @@
|
|||
<script setup>
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import IndexList from "@/components/index-list/index-list.vue";
|
||||
import { ref, computed } from "vue";
|
||||
import Tabs from "@/components/tabs/tabs.vue";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { data } = storeToRefs(userStore);
|
||||
const navList = [
|
||||
{ name: "审核中", id: 1 },
|
||||
{ name: "审核通过", id: 2 },
|
||||
{ name: "审核未通过", id: 3 },
|
||||
];
|
||||
const current = ref(0);
|
||||
const switchCurrent = (option) => {
|
||||
current.value = option.ind;
|
||||
};
|
||||
const list = computed(() => {
|
||||
console.log(data.value, "data.value");
|
||||
return data.value.release;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="我的发布" :left-arrow="true" :border="false"></nav-bar>
|
||||
<tabs
|
||||
:current="current"
|
||||
:list-num="3"
|
||||
:list="navList"
|
||||
switch-name="id"
|
||||
@on-switch="switchCurrent"
|
||||
></tabs>
|
||||
</tab-header>
|
||||
<content>
|
||||
<div class="list-box">
|
||||
<index-list :list="list"></index-list>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list-box {
|
||||
padding: 0 26px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,228 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
useNativeCamera,
|
||||
useNativeChooseFile,
|
||||
useNativeChooseMedia,
|
||||
useNativeRecordVideo,
|
||||
} from "@/assets/js/useNative.js";
|
||||
import { showToast } from "vant";
|
||||
import { pop } from "@/assets/js/useCustomRouter.js";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
|
||||
const userStore = useUserStore();
|
||||
const form = ref({
|
||||
username: "",
|
||||
type: "",
|
||||
cover: [],
|
||||
video: [],
|
||||
file: "",
|
||||
});
|
||||
const formField = ref("");
|
||||
const columns = ref([
|
||||
{ text: "经典转场", value: 1 },
|
||||
{ text: "唯美风景", value: 2 },
|
||||
{ text: "最火高清", value: 3 },
|
||||
]);
|
||||
const uploadColumns = ref([
|
||||
{ name: "拍摄", value: 1 },
|
||||
{ name: "从相册选择", value: 2 },
|
||||
]);
|
||||
const uploadType = ref("");
|
||||
const uploadPicker = ref(false);
|
||||
const showPicker = ref(false);
|
||||
const onConfirm = ({ selectedOptions }) => {
|
||||
showPicker.value = false;
|
||||
form.value.type = selectedOptions[0].text;
|
||||
};
|
||||
const uploadConfirm = (selectedValues) => {
|
||||
const param = { type: [uploadType.value], count: 1, multiple: false };
|
||||
uploadPicker.value = false;
|
||||
if (selectedValues.value === 2) {
|
||||
useNativeChooseMedia(param, (data) => {
|
||||
const imgItem = { url: data[0].path };
|
||||
form.value[formField.value].push(imgItem);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (uploadType.value === "image") {
|
||||
useNativeCamera({}, (data) => {
|
||||
const imgItem = { url: data.path };
|
||||
form.value[formField.value].push(imgItem);
|
||||
});
|
||||
return;
|
||||
}
|
||||
useNativeRecordVideo({}, (data) => {
|
||||
const videoItem = { url: data.path };
|
||||
form.value[formField.value].push(videoItem);
|
||||
});
|
||||
};
|
||||
const clickUpload = (field, type) => {
|
||||
uploadType.value = type;
|
||||
formField.value = field;
|
||||
uploadPicker.value = true;
|
||||
};
|
||||
const onSubmit = () => {
|
||||
form.value.url = form.value.cover[0].url;
|
||||
form.value.hot = 0;
|
||||
userStore.setUserData(form.value, "release");
|
||||
showToast({
|
||||
message: "保存成功",
|
||||
duration: 2000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
pop();
|
||||
}, 2000);
|
||||
};
|
||||
const upload = () => {
|
||||
useNativeChooseFile({ type: "doc" }, (data) => {
|
||||
console.log(data, "选择文件");
|
||||
form.value.file = data.path;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header>
|
||||
<nav-bar title="我要上传" :left-arrow="true" :border="false"></nav-bar>
|
||||
</tab-header>
|
||||
<content>
|
||||
<div class="form-box">
|
||||
<van-form @submit="onSubmit" input-align="right">
|
||||
<van-cell-group inset>
|
||||
<div class="group-box">
|
||||
<van-field
|
||||
v-model="form.type"
|
||||
is-link
|
||||
readonly
|
||||
name="picker"
|
||||
label="分类"
|
||||
placeholder="请选择分类"
|
||||
:rules="[{ required: true, message: '请选择分类' }]"
|
||||
@click="showPicker = true"
|
||||
/>
|
||||
</div>
|
||||
<div class="group-box">
|
||||
<van-field
|
||||
v-model="form.username"
|
||||
name="名称"
|
||||
label="名称"
|
||||
placeholder="请选择名称"
|
||||
:rules="[{ required: true, message: '请输入名称' }]"
|
||||
/>
|
||||
</div>
|
||||
<van-field
|
||||
name="uploader"
|
||||
label-align="top"
|
||||
input-align="left"
|
||||
label="上传封面"
|
||||
:rules="[{ required: true, message: '请上传封面图' }]"
|
||||
>
|
||||
<template #input>
|
||||
<div class="upload-box">
|
||||
<van-uploader
|
||||
@click-upload="clickUpload('cover', 'image')"
|
||||
:readonly="true"
|
||||
v-model="form.cover"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
name="uploader"
|
||||
label-align="top"
|
||||
input-align="left"
|
||||
label="上传视频"
|
||||
:rules="[{ required: true, message: '请上传视频' }]"
|
||||
>
|
||||
<template #input>
|
||||
<div class="upload-box">
|
||||
<van-uploader
|
||||
accept="video/*"
|
||||
@click-upload="clickUpload('video', 'video')"
|
||||
:readonly="true"
|
||||
v-model="form.video"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
name="uploader"
|
||||
label-align="top"
|
||||
input-align="left"
|
||||
label="上传文件"
|
||||
>
|
||||
<template #input>
|
||||
<van-button type="primary" @click="upload">上传文件</van-button>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-popup v-model:show="showPicker" position="bottom">
|
||||
<van-picker
|
||||
:columns="columns"
|
||||
@confirm="onConfirm"
|
||||
@cancel="showPicker = false"
|
||||
/>
|
||||
</van-popup>
|
||||
<van-action-sheet
|
||||
v-model:show="uploadPicker"
|
||||
:actions="uploadColumns"
|
||||
cancel-text="取消"
|
||||
@select="uploadConfirm"
|
||||
close-on-click-action
|
||||
@cancel="uploadPicker = false"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<div class="button-box">
|
||||
<van-button
|
||||
round
|
||||
block
|
||||
color="#FC5B5B"
|
||||
type="primary"
|
||||
native-type="submit"
|
||||
>
|
||||
提交
|
||||
</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.form-box {
|
||||
padding-top: 30px;
|
||||
}
|
||||
.group-box {
|
||||
padding: 15px 0;
|
||||
position: relative;
|
||||
&:after {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
content: " ";
|
||||
pointer-events: none;
|
||||
right: var(--van-padding-md);
|
||||
bottom: 0;
|
||||
left: var(--van-padding-md);
|
||||
border-bottom: 1px solid var(--van-cell-border-color);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
}
|
||||
.button-box {
|
||||
padding: 0 40px;
|
||||
position: fixed;
|
||||
bottom: 50px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.upload-box {
|
||||
padding: 15px 0;
|
||||
}
|
||||
:deep(.van-uploader__file-name.van-ellipsis) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,60 @@
|
|||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import IndexList from "@/components/index-list/index-list.vue";
|
||||
import Tabs from "@/components/tabs/tabs.vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const worksStore = useWorksStore();
|
||||
const { data } = storeToRefs(worksStore);
|
||||
|
||||
const navList = [
|
||||
{ name: "都市风格", id: "1" },
|
||||
{ name: "唯美风景", id: "2" },
|
||||
{ name: "黑白照片", id: "3" },
|
||||
];
|
||||
const hotList = computed(() => {
|
||||
return data.value.release.filter((item) => item.classify === "1");
|
||||
});
|
||||
window.pageShow = () => {
|
||||
console.log("页面显示");
|
||||
};
|
||||
window.pageHide = () => {
|
||||
console.log("页面隐藏");
|
||||
};
|
||||
const list = ref([]);
|
||||
const current = ref(0);
|
||||
const switchCurrent = (option) => {
|
||||
current.value = option.ind;
|
||||
list.value = hotList.value.filter((item) => item.type === option.name);
|
||||
};
|
||||
switchCurrent({ ind: 0, name: "1" });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="平台作品" :left-arrow="true" :border="false"></nav-bar>
|
||||
<tabs
|
||||
:current="current"
|
||||
:list-num="3"
|
||||
switch-name="id"
|
||||
:list="navList"
|
||||
@on-switch="switchCurrent"
|
||||
></tabs>
|
||||
</tab-header>
|
||||
<content :padding-top="110">
|
||||
<div class="list-box">
|
||||
<index-list :list="list"></index-list>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list-box {
|
||||
padding: 0 26px 55px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="隐私协议" :left-arrow="true" :border="false"></nav-bar>
|
||||
</tab-header>
|
||||
<iframe
|
||||
src="https://jpfz.qhdsafety.com/demo/privacy.html"
|
||||
style="width: 100vw; height: calc(100vh - 48px); margin-top: 48px"
|
||||
frameborder="0"
|
||||
allowfullscreen="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
</script>
|
|
@ -0,0 +1,262 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import err1 from "@/assets/images/err-icon1.png";
|
||||
import err2 from "@/assets/images/err-icon2.png";
|
||||
import err3 from "@/assets/images/err-icon3.png";
|
||||
import err4 from "@/assets/images/err-icon4.png";
|
||||
import err5 from "@/assets/images/err-icon5.png";
|
||||
import {
|
||||
useNativeCamera,
|
||||
useNativeChooseMedia,
|
||||
useNativeRecordVideo,
|
||||
} from "@/assets/js/useNative.js";
|
||||
import { showToast } from "vant";
|
||||
import { pop } from "@/assets/js/useCustomRouter.js";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const form = ref({
|
||||
username: "",
|
||||
cover: [],
|
||||
errType: undefined,
|
||||
});
|
||||
const errorList = [
|
||||
{ id: "1", url: err1, name: "系统错误" },
|
||||
{ id: "2", url: err2, name: "界面优化" },
|
||||
{ id: "3", url: err3, name: "设计缺陷" },
|
||||
{ id: "4", url: err4, name: "性能问题" },
|
||||
{ id: "5", url: err5, name: "其他问题" },
|
||||
];
|
||||
const uploadColumns = ref([
|
||||
{ name: "拍摄", value: 1 },
|
||||
{ name: "从相册选择", value: 2 },
|
||||
]);
|
||||
const formField = ref("");
|
||||
const uploadType = ref("");
|
||||
const uploadPicker = ref(false);
|
||||
const uploadConfirm = (selectedValues) => {
|
||||
const param = { type: [uploadType.value], count: 1, multiple: false };
|
||||
uploadPicker.value = false;
|
||||
if (selectedValues.value === 2) {
|
||||
useNativeChooseMedia(param, (data) => {
|
||||
const imgItem = { url: data[0].path };
|
||||
form.value[formField.value].push(imgItem);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (uploadType.value === "image") {
|
||||
useNativeCamera({}, (data) => {
|
||||
const imgItem = { url: data.path };
|
||||
form.value[formField.value].push(imgItem);
|
||||
});
|
||||
return;
|
||||
}
|
||||
useNativeRecordVideo({}, (data) => {
|
||||
const videoItem = { url: data.path };
|
||||
form.value[formField.value].push(videoItem);
|
||||
});
|
||||
};
|
||||
const clickUpload = (field, type) => {
|
||||
uploadType.value = type;
|
||||
formField.value = field;
|
||||
uploadPicker.value = true;
|
||||
};
|
||||
const selectErrType = (id) => {
|
||||
form.value.errType = id;
|
||||
};
|
||||
const onSubmit = () => {
|
||||
showToast({
|
||||
message: "保存成功",
|
||||
duration: 2000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
pop();
|
||||
}, 2000);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<div
|
||||
class="head"
|
||||
:style="{ paddingTop: systemInfo.batteryBarsHeight + 'px' }"
|
||||
>
|
||||
<nav-bar title="问题反馈" :left-arrow="true" :border="false"></nav-bar>
|
||||
</div>
|
||||
<div class="content-box">
|
||||
<van-form @submit="onSubmit" input-align="left">
|
||||
<van-cell-group inset>
|
||||
<div class="group-box">
|
||||
<van-field
|
||||
v-model="form.username"
|
||||
name="标题"
|
||||
label=""
|
||||
placeholder="请输入标题"
|
||||
:rules="[{ required: true, message: '请输入标题' }]"
|
||||
/>
|
||||
</div>
|
||||
<div class="error-box">
|
||||
<van-field
|
||||
name="错误类型"
|
||||
v-model="form.errType"
|
||||
label=""
|
||||
:rules="[{ required: true, message: '请选择错误类型' }]"
|
||||
>
|
||||
<template #input>
|
||||
<div class="error-list">
|
||||
<div
|
||||
class="error-item"
|
||||
:class="{ active: form.errType === item.id }"
|
||||
v-for="item in errorList"
|
||||
:key="item.id"
|
||||
@click="selectErrType(item.id)"
|
||||
>
|
||||
<img :src="item.url" :alt="item.name" />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
</div>
|
||||
<div class="content">
|
||||
<span>我要反馈</span>
|
||||
<div class="content-child">
|
||||
<van-field
|
||||
:border="false"
|
||||
v-model="form.message"
|
||||
rows="1"
|
||||
autosize
|
||||
label=""
|
||||
type="textarea"
|
||||
placeholder="你想说点什么"
|
||||
/>
|
||||
<van-field
|
||||
name="uploader"
|
||||
label-align="top"
|
||||
input-align="left"
|
||||
label=""
|
||||
>
|
||||
<template #input>
|
||||
<div class="upload-box">
|
||||
<van-uploader
|
||||
:readonly="true"
|
||||
v-model="form.cover"
|
||||
@click-upload="clickUpload('cover', 'image')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
</div>
|
||||
</div>
|
||||
<van-action-sheet
|
||||
v-model:show="uploadPicker"
|
||||
:actions="uploadColumns"
|
||||
cancel-text="取消"
|
||||
@select="uploadConfirm"
|
||||
close-on-click-action
|
||||
@cancel="uploadPicker = false"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<button class="submit">确定</button>
|
||||
</van-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.head {
|
||||
background-color: #1082ff;
|
||||
:deep(.van-nav-bar) {
|
||||
background-color: #1082ff;
|
||||
.van-nav-bar__title {
|
||||
color: #fff;
|
||||
}
|
||||
.van-icon {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-box {
|
||||
margin-top: 26px;
|
||||
.group-box {
|
||||
position: relative;
|
||||
&:after {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
content: " ";
|
||||
pointer-events: none;
|
||||
right: var(--van-padding-md);
|
||||
bottom: 0;
|
||||
left: var(--van-padding-md);
|
||||
border-bottom: 1px solid var(--van-cell-border-color);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
.error-box {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.error-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.error-item {
|
||||
width: calc((100% - 64px) / 3);
|
||||
padding: 33px 0 26px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 32px;
|
||||
background: #f6f7fb;
|
||||
border-radius: 7px;
|
||||
&:nth-child(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
img {
|
||||
width: 40px;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: 27px;
|
||||
color: #9fa7bc;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
.active {
|
||||
background-color: #1082ff;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 0 32px;
|
||||
> span {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.content-child {
|
||||
background-color: #f8f9fd;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
.van-uploader__upload {
|
||||
border: 4px dashed #c1c4cd;
|
||||
border-radius: 17px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.submit {
|
||||
display: block;
|
||||
width: calc(100% - 64px);
|
||||
line-height: 99px;
|
||||
background-color: #1082ff;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #1082ff;
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
color: #ffffff;
|
||||
margin: 64px auto 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,133 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import { redirect } from "@/assets/js/useCustomRouter.js";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
|
||||
const historyList = ref([]);
|
||||
const hotList = ref([
|
||||
{ name: "都市", id: "1" },
|
||||
{ name: "风景", id: 2 },
|
||||
{ name: "雪", id: 2 },
|
||||
]);
|
||||
const searchValue = ref("");
|
||||
const onSearch = () => {
|
||||
console.log("重定向跳转");
|
||||
redirect({
|
||||
url: "/search/search_list",
|
||||
params: {
|
||||
value: searchValue.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
const selectSearch = (value) => {
|
||||
searchValue.value = value;
|
||||
onSearch();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header>
|
||||
<nav-bar title="搜索" :left-arrow="true" :border="false"></nav-bar>
|
||||
</tab-header>
|
||||
<content :padding-top="30">
|
||||
<div class="search-box">
|
||||
<div class="search">
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchValue"
|
||||
maxlength="8"
|
||||
placeholder="搜索您需要的素材"
|
||||
/>
|
||||
<van-icon name="search" size="20px" />
|
||||
</div>
|
||||
<span @click="onSearch">搜索</span>
|
||||
</div>
|
||||
<div class="search-nav">
|
||||
<span class="title">历史搜索</span>
|
||||
<div class="search-nav-box">
|
||||
<span
|
||||
v-for="item in historyList"
|
||||
:key="item.name"
|
||||
@click="selectSearch(item.name)"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-nav">
|
||||
<span class="title">推荐搜索</span>
|
||||
<div class="search-nav-box">
|
||||
<span
|
||||
v-for="item in hotList"
|
||||
:key="item.name"
|
||||
@click="selectSearch(item.name)"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-box {
|
||||
margin-top: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 25px;
|
||||
padding-bottom: 30px;
|
||||
> span {
|
||||
font-size: 28px;
|
||||
color: #ff420c;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
}
|
||||
.search {
|
||||
flex: 1;
|
||||
height: 88px;
|
||||
background-color: #f6f7f8;
|
||||
border-radius: 44px;
|
||||
border: 1px solid #ececec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 36px 0 30px;
|
||||
input {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
height: 100%;
|
||||
background-color: #f6f7f8;
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
}
|
||||
}
|
||||
.search-nav {
|
||||
margin-top: 60px;
|
||||
padding: 0 25px;
|
||||
.title {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
font-size: 35px;
|
||||
color: #222222;
|
||||
margin-bottom: 38px;
|
||||
}
|
||||
.search-nav-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
span {
|
||||
min-width: 140px;
|
||||
padding: 0 26px;
|
||||
margin-right: 30px;
|
||||
margin-bottom: 30px;
|
||||
background-color: #f6f7f8;
|
||||
border-radius: 24px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
color: #444444;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,226 @@
|
|||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { pop, push } from "@/assets/js/useCustomRouter.js";
|
||||
import { useRoute } from "vue-router";
|
||||
import IndexList from "@/components/index-list/index-list.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
import Content from "@/components/content/content.vue";
|
||||
import { useWorksStore } from "@/pinia/works.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
const worksStore = useWorksStore();
|
||||
const { data } = storeToRefs(worksStore);
|
||||
const route = useRoute();
|
||||
const details = route.query;
|
||||
window.initData = (data) => {
|
||||
console.log(data, "获取参数");
|
||||
};
|
||||
const searchValue = ref(details.value);
|
||||
|
||||
const current = ref(0);
|
||||
const tabList = ref([
|
||||
{ name: "素材", type: 1 },
|
||||
{ name: "文案", type: 2 },
|
||||
]);
|
||||
const searchList = ref([]);
|
||||
const allMaterial = computed(() => {
|
||||
return data.value.release;
|
||||
});
|
||||
const list = ref([
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/799/300/400.jpg?hmac=skUMPxX6ZcZmkbpXkyOV7flzeglSNvp1fNcEvoU6e1c",
|
||||
name: "你的生活再苦,别人也没法替你承担。想要的东西,只能自己去赚去拼。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/518/400/300.jpg?hmac=SBiwfW8E5aDfYKLvB6-s-pp7SA7WntrI8GjPkpzhd_k",
|
||||
name: "前方的路可能充满崎岖唯有奋斗才能不惧风雨。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/65/300/400.jpg?hmac=lhM904DByZf8WL8u56mtPZO9TA_ipwYDTOoatdjPzx4",
|
||||
name: "不要瞻前顾后,拼尽全力向前奔跑吧。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/239/300/300.jpg?hmac=esyLH7XPNWHLXWLu_Dvs59SpxUEnrBHF4FV_02YOak4",
|
||||
name: "真正的努力大多是默默的、不起眼的、不叫嚣的,人大多是不知不觉。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/317/300/300.jpg?hmac=gg_enWI-dwSZM7YuLo3LA-dVghfkTvugM7iukp_4RR0",
|
||||
name: "以风筝之线为始,以彩虹之海为终。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/408/300/400.jpg?hmac=1pTfKCG8_tiCVSoQSOYZ8zlKnh2jBmhZWpf3zy9X0hc",
|
||||
name: "老人说,今天他来晚了,钓的是一篓暮色,明天他要早起,一定能钓到一江朝阳。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/866/200/300.jpg?hmac=rcadCENKh4rD6MAp6V_ma-AyWv641M4iiOpe1RyFHeI",
|
||||
name: "我曾看到一个时间旅人,从身上拍落两场大雪,由心里携出一篮火焰,独自穿过整个冬天。",
|
||||
},
|
||||
{
|
||||
url: "https://fastly.picsum.photos/id/417/400/300.jpg?hmac=AeJwv7oRTFt1ifIPEbJFXw1B0qYJVeauRbaOXUhnmAY",
|
||||
name: "所谓压力,其实是自身的能力不足;所谓困难,其实是自己的本事不够",
|
||||
},
|
||||
]);
|
||||
const onSearch = (ind) => {
|
||||
if (ind === 1) {
|
||||
searchList.value = allMaterial.value.filter((item) => {
|
||||
return item.name.indexOf(searchValue.value) !== -1;
|
||||
});
|
||||
return;
|
||||
}
|
||||
console.log(searchList.value);
|
||||
searchList.value = list.value.filter((item) => {
|
||||
return item.name.indexOf(searchValue.value) !== -1;
|
||||
});
|
||||
console.log(searchList.value);
|
||||
};
|
||||
|
||||
const switchType = (ind) => {
|
||||
current.value = ind;
|
||||
onSearch(ind);
|
||||
};
|
||||
const viewDetails = (item) => {
|
||||
push({
|
||||
url: "/material/material_details",
|
||||
params: item,
|
||||
});
|
||||
};
|
||||
const back = () => {
|
||||
pop();
|
||||
};
|
||||
switchType(1);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<tab-header :sticky="true">
|
||||
<div>
|
||||
<div class="header">
|
||||
<van-icon
|
||||
name="arrow-left"
|
||||
color="#3C3B3B"
|
||||
size="20px"
|
||||
@click="back"
|
||||
/>
|
||||
<div class="search-box">
|
||||
<div class="search">
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchValue"
|
||||
maxlength="8"
|
||||
placeholder="搜索您需要的素材"
|
||||
/>
|
||||
<van-icon name="search" size="20px" />
|
||||
</div>
|
||||
<span @click="onSearch(current)">搜索</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<span
|
||||
v-for="item in tabList"
|
||||
:key="item.name"
|
||||
:class="{ active: current === item.type }"
|
||||
@click="switchType(item.type)"
|
||||
>{{ item.name }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</tab-header>
|
||||
|
||||
<content :padding-top="70">
|
||||
<div class="list-box" v-if="current === 1">
|
||||
<index-list :list="searchList"></index-list>
|
||||
</div>
|
||||
<div class="content-list" v-if="current === 2">
|
||||
<div
|
||||
class="content-list-item"
|
||||
v-for="item in searchList"
|
||||
:key="item.name"
|
||||
@click="viewDetails(item)"
|
||||
>
|
||||
<img :src="item.url" alt="" />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 50px 20px 26px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 25px;
|
||||
> span {
|
||||
font-size: 28px;
|
||||
color: #ff420c;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
}
|
||||
.search {
|
||||
flex: 1;
|
||||
height: 88px;
|
||||
margin-left: 15px;
|
||||
background-color: #f6f7f8;
|
||||
border-radius: 44px;
|
||||
border: 1px solid #ececec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 36px 0 30px;
|
||||
input {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
height: 100%;
|
||||
background-color: #f6f7f8;
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
font-size: 27px;
|
||||
}
|
||||
}
|
||||
.tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 26px 10px 26px;
|
||||
background-color: #fff;
|
||||
span {
|
||||
padding: 0 25px;
|
||||
color: #999999;
|
||||
font-size: 26px;
|
||||
}
|
||||
.active {
|
||||
font-size: 32px;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.content-list {
|
||||
-moz-column-count: 2; /* Firefox */
|
||||
-webkit-column-count: 2; /* Safari 和 Chrome */
|
||||
column-count: 2;
|
||||
column-gap: 16px;
|
||||
padding: 26px;
|
||||
.content-list-item {
|
||||
margin-bottom: 20px;
|
||||
break-inside: avoid;
|
||||
img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
border-radius: 10px;
|
||||
}
|
||||
span {
|
||||
display: block;
|
||||
margin-top: 15px;
|
||||
font-size: 30px;
|
||||
line-height: 35px;
|
||||
font-weight: bold;
|
||||
color: #3a3a3c;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-box {
|
||||
padding: 0 26px 55px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,283 @@
|
|||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import Tabbar from "@/components/tabbar/tabbar.vue";
|
||||
import { push, reLaunch } from "@/assets/js/useCustomRouter.js";
|
||||
import {
|
||||
getUpdateVersion,
|
||||
// useNativeActivateCamera,
|
||||
// useNativeActivateCameraClose,
|
||||
// useNativeActivateCameraSetMessage,
|
||||
// useNativeGetLocation,
|
||||
// useNativeGetPermission,
|
||||
// useNativePushClientId,
|
||||
// useNativeSystemInfo,
|
||||
// useNativePreviewFile,
|
||||
// useNativeGetNetworkType,
|
||||
// useNativeGetVersion,
|
||||
// useNativeOpenBrowser,
|
||||
// useNativeQuitApp,
|
||||
} from "@/assets/js/useNative.js";
|
||||
import { useUserStore } from "@/pinia/user.js";
|
||||
import Content from "@/components/content/content.vue";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
const store = systemInfoStore();
|
||||
const { systemInfo } = storeToRefs(store);
|
||||
const userStore = useUserStore();
|
||||
const { data } = storeToRefs(userStore);
|
||||
const navLst = ref([
|
||||
{
|
||||
name: "我的发布",
|
||||
fun: () => {
|
||||
push({ url: "/user/my_release", params: {} });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "修改密码",
|
||||
fun: () => {
|
||||
push({ url: "/change_password", params: {} });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "版本更新",
|
||||
fun: () => {
|
||||
console.log("版本更新");
|
||||
getUpdateVersion();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "意见反馈",
|
||||
fun: () => {
|
||||
push({ url: "/user/problem_feedback", params: {} });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "隐私协议",
|
||||
fun: () => {
|
||||
push({ url: "/user/privacy_agreement", params: {} });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "用户协议",
|
||||
fun: () => {
|
||||
push({ url: "/user/user_agreement", params: {} });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "注销",
|
||||
fun: () => {
|
||||
push({ url: "/cancel_account", params: {} });
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: "获取定位",
|
||||
// fun: () => {
|
||||
// useNativeGetLocation({}, (data) => {
|
||||
// console.log(data, "定位地址");
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "获取设备信息",
|
||||
// fun: () => {
|
||||
// useNativeSystemInfo({}, (data) => {
|
||||
// console.log(data, "设备信息");
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "消息推送CID",
|
||||
// fun: () => {
|
||||
// useNativePushClientId({}, (data) => {
|
||||
// console.log(data, "消息推送CID");
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "查询定位权限",
|
||||
// fun: () => {
|
||||
// useNativeGetPermission(
|
||||
// { type: "location", title: "定位权限", describe: "定位权限" },
|
||||
// (data) => {
|
||||
// console.log(data, "权限");
|
||||
// },
|
||||
// );
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "第三方app打开附件",
|
||||
// fun: () => {
|
||||
// useNativePreviewFile({
|
||||
// url: "https://jpfz.qhdsafety.com/demo/%E9%99%84%E4%BB%B6.doc",
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "获取当前网络",
|
||||
// fun: () => {
|
||||
// useNativeGetNetworkType({}, (data) => {
|
||||
// console.log(data, "当前网络");
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "获取当前版本",
|
||||
// fun: () => {
|
||||
// useNativeGetVersion({}, (data) => {
|
||||
// console.log(data, "当前版本");
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "打开网址",
|
||||
// fun: () => {
|
||||
// useNativeOpenBrowser({ url: "https://www.baidu.com/" });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "退出app",
|
||||
// fun: () => {
|
||||
// useNativeQuitApp({});
|
||||
// },
|
||||
// },
|
||||
]);
|
||||
window.pageShow = () => {
|
||||
console.log("页面显示");
|
||||
};
|
||||
window.pageHide = () => {
|
||||
console.log("页面隐藏");
|
||||
};
|
||||
// const replace = () => {
|
||||
// const num = 0;
|
||||
// useNativeActivateCamera({ interval: 2000 }, (data) => {
|
||||
// console.log(data, "拍摄返回值");
|
||||
// });
|
||||
// useNativeActivateCameraSetMessage({ message: "拍摄头像" });
|
||||
// numNext(num);
|
||||
// };
|
||||
// const numNext = (num) => {
|
||||
// console.log("num", num);
|
||||
// useNativeActivateCameraSetMessage({ message: "拍摄头像" + num });
|
||||
// if (num < 10) {
|
||||
// num++;
|
||||
// setTimeout(() => {
|
||||
// numNext(num);
|
||||
// }, 1000);
|
||||
// } else {
|
||||
// console.log("关闭");
|
||||
// useNativeActivateCameraClose();
|
||||
// }
|
||||
// };
|
||||
const logout = () => {
|
||||
// useNativeQuitApp();
|
||||
reLaunch({
|
||||
url: "/login",
|
||||
params: {},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<div>
|
||||
<div
|
||||
class="user-head"
|
||||
:style="{
|
||||
paddingTop: systemInfo.batteryBarsHeight + 'px',
|
||||
}"
|
||||
>
|
||||
<span>个人中心</span>
|
||||
</div>
|
||||
</div>
|
||||
<content :padding-bottom="162">
|
||||
<div class="header">
|
||||
<div class="user-box">
|
||||
<img src="@/assets/images/user_pic.png" alt="" />
|
||||
<span>用户{{ data.userInfo.userName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-list">
|
||||
<div
|
||||
class="nav-list-item"
|
||||
v-for="(item, index) in navLst"
|
||||
:key="index"
|
||||
@click="item.fun"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
<van-icon name="arrow" color="#999999" size="14px" />
|
||||
</div>
|
||||
</div>
|
||||
<button class="logout" @click="logout">退出登录</button>
|
||||
</content>
|
||||
<tabbar select-tab="user"></tabbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrap {
|
||||
background-color: #f9f9f9;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 126px;
|
||||
}
|
||||
.header {
|
||||
padding: 0 0 50px;
|
||||
flex-direction: column;
|
||||
background-image: url("../../assets/images/login_bj.jpg");
|
||||
background-size: cover;
|
||||
background-position: top center;
|
||||
.user-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 35px;
|
||||
img {
|
||||
width: 120px;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #fff;
|
||||
margin-right: 25px;
|
||||
}
|
||||
span {
|
||||
font-weight: bold;
|
||||
font-size: 29px;
|
||||
color: #222222;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.van-nav-bar) {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
.user-head {
|
||||
//padding-top: 100px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
.nav-list {
|
||||
margin: 20px 31px 50px;
|
||||
border-radius: 13px;
|
||||
background-color: #fff;
|
||||
padding: 37px 34px;
|
||||
.nav-list-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span {
|
||||
font-weight: bold;
|
||||
font-size: 29px;
|
||||
color: #222222;
|
||||
line-height: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.logout {
|
||||
display: block;
|
||||
margin: 0 31px;
|
||||
line-height: 100px;
|
||||
background: #f0eeee;
|
||||
border-radius: 13px;
|
||||
width: calc(100% - 62px);
|
||||
border: 1px solid #f0eeee;
|
||||
font-weight: bold;
|
||||
font-size: 29px;
|
||||
color: rgba(102, 102, 102, 0.54);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<tab-header :sticky="true">
|
||||
<nav-bar title="用户协议" :left-arrow="true" :border="false"></nav-bar>
|
||||
</tab-header>
|
||||
<iframe
|
||||
src="https://jpfz.qhdsafety.com/demo/users_agreement.html"
|
||||
style="width: 100vw; height: calc(100vh - 48px); margin-top: 48px"
|
||||
frameborder="0"
|
||||
allowfullscreen="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||||
import TabHeader from "@/components/head/head.vue";
|
||||
</script>
|
|
@ -0,0 +1,83 @@
|
|||
import { defineConfig, loadEnv } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import eslintPlugin from "vite-plugin-eslint";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
import { VantResolver } from "unplugin-vue-components/resolvers";
|
||||
import EnhanceLog from "vite-plugin-enhance-log";
|
||||
// import removeConsole from "vite-plugin-remove-console";
|
||||
|
||||
export default ({ mode }) => {
|
||||
return defineConfig({
|
||||
base: loadEnv(mode, process.cwd()).VITE_BASE,
|
||||
plugins: [
|
||||
vue(),
|
||||
eslintPlugin(),
|
||||
Components({
|
||||
resolvers: [VantResolver()],
|
||||
}),
|
||||
// removeConsole({
|
||||
// includes: [
|
||||
// "assert",
|
||||
// "clear",
|
||||
// "count",
|
||||
// "countReset",
|
||||
// "createTask",
|
||||
// "debug",
|
||||
// "dir",
|
||||
// "dirxml",
|
||||
// "error",
|
||||
// "group",
|
||||
// "groupCollapsed",
|
||||
// "groupEnd",
|
||||
// "info",
|
||||
// "log",
|
||||
// "profile",
|
||||
// "profileEnd",
|
||||
// "table",
|
||||
// "time",
|
||||
// "timeEnd",
|
||||
// "timeLog",
|
||||
// "timeStamp",
|
||||
// "trace",
|
||||
// "warn",
|
||||
// ],
|
||||
// }),
|
||||
EnhanceLog({
|
||||
preTip: "🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀",
|
||||
}),
|
||||
],
|
||||
server: {
|
||||
host: true, // 本机的局域网IP,不然其他人无法通过IP访问到,0.0.0.0或true会自动获取本机的IP
|
||||
port: 8099, // 端口号
|
||||
open: true, // 是否自动打开浏览器
|
||||
proxy: {
|
||||
[loadEnv(mode, process.cwd()).VITE_PROXY]: {
|
||||
target: loadEnv(mode, process.cwd()).VITE_BASE_URL,
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": "/src", // 别名,@代表src目录
|
||||
},
|
||||
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"], // 引入文件时哪些后缀名可以不写
|
||||
},
|
||||
build: {
|
||||
rollupOptions: {
|
||||
// 打包多个入口文件
|
||||
// input: {
|
||||
// admin: path.resolve(__dirname, "index.html"),
|
||||
// 其它入口文件路径需要为src/views/*/index.html
|
||||
// },
|
||||
output: {
|
||||
chunkFileNames: "static/js/[name]-[hash].js",
|
||||
entryFileNames: "static/js/[name]-[hash].js",
|
||||
assetFileNames: "static/[ext]/name-[hash].[ext]",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
VITE_BASE_URL=1
|
||||
VITE_PROXY=/api
|
||||
VITE_FILE_PATH=1
|
||||
|
|
@ -0,0 +1 @@
|
|||
VITE_BASE=/
|
|
@ -0,0 +1 @@
|
|||
VITE_BASE=/demo
|
|
@ -0,0 +1,4 @@
|
|||
public
|
||||
dist
|
||||
package.json
|
||||
!.prettierrc.cjs
|
|
@ -0,0 +1,62 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"standard",
|
||||
"@vue/prettier",
|
||||
"eslint:recommended",
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["vue"],
|
||||
rules: {
|
||||
"no-console": "warn",
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-v-html": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"camelcase": "off",
|
||||
"eqeqeq": "error",
|
||||
"vue/no-template-shadow": "error",
|
||||
"vue/attribute-hyphenation": "error",
|
||||
"vue/html-end-tags": "error",
|
||||
"vue/eqeqeq": "error",
|
||||
"vue/component-name-in-template-casing": ["error", "kebab-case"],
|
||||
"vue/enforce-style-attribute": [
|
||||
"error",
|
||||
{ "allow": ["scoped", "module"] }
|
||||
],
|
||||
"vue/v-on-event-hyphenation": ["error", "always",{
|
||||
"autofix": true,
|
||||
}],
|
||||
"vue/require-explicit-emits": "error",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "VariableDeclarator[id.name='pd']",
|
||||
"message": "不允许使用 pd,请改用有语义化的变量名"
|
||||
},
|
||||
{
|
||||
"selector": "ObjectExpression > Property[key.name='pd']",
|
||||
"message": "不允许使用 pd,请改用有语义化的变量名"
|
||||
},
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{ vars: "all", args: "after-used", ignoreRestSiblings: false }
|
||||
],
|
||||
"linebreak-style": ["off",'windows'],
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{ "object": "Object", "property": "assign"}
|
||||
],
|
||||
},
|
||||
globals: {
|
||||
defineOptions: "readonly",
|
||||
},
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
extends: ["@vue/prettier", "plugin:prettier/recommended"],
|
||||
endOfLine: "crlf",
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
# Vue 3 + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
|
||||
<title>demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<noscript>
|
||||
<strong>很抱歉,如果没有启用JavaScript,网站无法正常工作,请启用JavaScript使其正常工作。</strong>
|
||||
</noscript>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "demo",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue --fix src .prettierrc.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vant/weapp": "^1.11.7",
|
||||
"@vueuse/core": "^10.11.1",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.7.4",
|
||||
"dayjs": "^1.11.12",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.2.1",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qs": "^6.13.0",
|
||||
"throttle-debounce": "^5.0.2",
|
||||
"vant": "^4.9.4",
|
||||
"vue": "^3.4.37",
|
||||
"vue-router": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.3.0",
|
||||
"@vitejs/plugin-vue": "^5.1.2",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"cnjm-postcss-px-to-viewport": "^1.0.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"prettier": "^3.3.3",
|
||||
"sass": "^1.77.8",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vconsole": "^3.15.1",
|
||||
"vite": "^5.4.0",
|
||||
"vite-plugin-checker": "^0.7.2",
|
||||
"vite-plugin-enhance-log": "^0.6.2",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-remove-console": "^2.2.0",
|
||||
"vue-eslint-parser": "^9.4.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
const path = require('path')
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {
|
||||
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8', '> 1%'],
|
||||
grid: true,
|
||||
},
|
||||
"cnjm-postcss-px-to-viewport": {
|
||||
unitToConvert: "px", // 要转化的单位
|
||||
viewportWidth: 750, // UI设计稿的宽度
|
||||
unitPrecision: 6, // 转换后的精度,即小数点位数
|
||||
propList: ["*"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
|
||||
viewportUnit: "vw", // 指定需要转换成的视窗单位,默认vw
|
||||
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw
|
||||
selectorBlackList: [".ignore", ".hairlines"],
|
||||
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
|
||||
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
|
||||
replace: true, // 是否转换后直接更换属性值
|
||||
exclude: [], // 设置忽略文件,用正则做目录名匹配
|
||||
landscape: false, // 是否处理横屏情况
|
||||
// 如果没有使用其他的尺寸来设计,下面这个方法可以不需要,比如vant是375的
|
||||
customFun: ({ file }) => {
|
||||
// 这个自定义的方法是针对处理vant组件下的设计稿为375问题
|
||||
return path.join(file).includes(path.join("node_modules", "vant"))
|
||||
? 375
|
||||
: 750;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<suspense>
|
||||
<template #default>
|
||||
<div>
|
||||
<van-overlay :show="miscellaneousStore.getLoading">
|
||||
<van-loading color="#fff" size="24px" vertical>加载中...</van-loading>
|
||||
</van-overlay>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
<template #fallback>
|
||||
<div>加载中...</div>
|
||||
</template>
|
||||
</suspense>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRoute } from "vue-router";
|
||||
import { watchEffect } from "vue";
|
||||
import { useMiscellaneousStore } from "@/pinia/miscellaneous.js";
|
||||
import { systemInfoStore } from "@/pinia/systemInfo.js";
|
||||
import { useNativeGetStatusBarHeight } from "@/assets/js/useNative.js";
|
||||
const store = systemInfoStore();
|
||||
const miscellaneousStore = useMiscellaneousStore();
|
||||
const route = useRoute();
|
||||
watchEffect(() => {
|
||||
window.document.title = route.meta.title;
|
||||
});
|
||||
window.appShow = () => {
|
||||
console.log("app显示了");
|
||||
};
|
||||
window.appHide = () => {
|
||||
console.log("app隐藏了");
|
||||
};
|
||||
const getBarHeight = () => {
|
||||
useNativeGetStatusBarHeight({}, (data) => {
|
||||
console.log(data, "电池栏高度");
|
||||
store.setSystemInfo(data.height, "batteryBarsHeight");
|
||||
if (data.bottomSafeHeight) {
|
||||
store.setSystemInfo(data.bottomSafeHeight, "bottomSafeHeight");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getBarHeight();
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:root {
|
||||
--van-uploader-size: 146px !important;
|
||||
--van-button-mini-padding: 0 20px !important;
|
||||
--van-nav-bar-z-index: 9 !important;
|
||||
--van-nav-bar-background: rgb(51, 119, 255) !important;
|
||||
--van-nav-bar-title-text-color: var(--van-white) !important;
|
||||
--van-nav-bar-icon-color: var(--van-white) !important;
|
||||
--van-nav-bar-text-color: var(--van-white) !important;
|
||||
}
|
||||
#app {
|
||||
background-color: #fafafa;
|
||||
min-height: 100vh;
|
||||
font-size: 30px;
|
||||
}
|
||||
.van-loading {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,26 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
overflow: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
// 文字超出几行隐藏,最多5行
|
||||
// 使用超出1行隐藏,如果使用了flex,则需要给父元素设置min-width: 0;
|
||||
@for $i from 1 through 5 {
|
||||
.line-#{$i} {
|
||||
@if $i == 1 {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical !important;
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 13 KiB |