first
2
.env.development
Normal file
@ -0,0 +1,2 @@
|
||||
# VITE_BASE_URL="http://dev.edu.igandan.com/gdxz-h5/"
|
||||
VITE_BASE_URL="https://dev-caseplatform.igandan.com/api/"
|
||||
2
.env.production
Normal file
@ -0,0 +1,2 @@
|
||||
# VITE_BASE_URL="http://dev.edu.igandan.com/gdxz-h5/"
|
||||
VITE_BASE_URL="https://prod-caseplatform.igandan.com/api/"
|
||||
2
.env.test
Normal file
@ -0,0 +1,2 @@
|
||||
# VITE_BASE_URL="https://twx.igandan.org/"
|
||||
VITE_BASE_URL="https://dev-caseplatform.igandan.com/api/"
|
||||
51
.gitignore
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
|
||||
# eslint
|
||||
.eslintcache
|
||||
|
||||
# stylelint
|
||||
.stylelintcache
|
||||
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
/dist*
|
||||
|
||||
stats.html
|
||||
65
auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
|
||||
}
|
||||
45
components.d.ts
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
Back: typeof import('./src/components/back.vue')['default']
|
||||
CaseDetail: typeof import('./src/views/caseDetail.vue')['default']
|
||||
CaseIntro: typeof import('./src/views/caseIntro.vue')['default']
|
||||
CaseList: typeof import('./src/views/caseList.vue')['default']
|
||||
CDialog: typeof import('./src/components/c-dialog.vue')['default']
|
||||
CList: typeof import('./src/components/c-list.vue')['default']
|
||||
Comment: typeof import('./src/views/comment.vue')['default']
|
||||
CommentList: typeof import('./src/components/comment-list.vue')['default']
|
||||
Commentunit: typeof import('./src/components/commentunit.vue')['default']
|
||||
Expandunit: typeof import('./src/components/expandunit.vue')['default']
|
||||
Home: typeof import('./src/views/home.vue')['default']
|
||||
Loading: typeof import('./src/components/loading/loading.vue')['default']
|
||||
Pageunit: typeof import('./src/views/pageunit.vue')['default']
|
||||
Question: typeof import('./src/components/question.vue')['default']
|
||||
Questionend: typeof import('./src/components/questionend.vue')['default']
|
||||
Reply: typeof import('./src/components/reply.vue')['default']
|
||||
Result: typeof import('./src/views/result.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SingleQuestion: typeof import('./src/components/singleQuestion.vue')['default']
|
||||
TopicList: typeof import('./src/components/topicList.vue')['default']
|
||||
Totop: typeof import('./src/components/totop.vue')['default']
|
||||
VanCheckbox: typeof import('vant/es')['Checkbox']
|
||||
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
|
||||
VanField: typeof import('vant/es')['Field']
|
||||
VanImage: typeof import('vant/es')['Image']
|
||||
VanImagePreview: typeof import('vant/es')['ImagePreview']
|
||||
VanList: typeof import('vant/es')['List']
|
||||
VanOverlay: typeof import('vant/es')['Overlay']
|
||||
VanPullRefresh: typeof import('vant/es')['PullRefresh']
|
||||
VanRadio: typeof import('vant/es')['Radio']
|
||||
VanRadioGroup: typeof import('vant/es')['RadioGroup']
|
||||
VanTab: typeof import('vant/es')['Tab']
|
||||
VanTabs: typeof import('vant/es')['Tabs']
|
||||
}
|
||||
}
|
||||
119
index.html
Normal file
@ -0,0 +1,119 @@
|
||||
<!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, user-scalable=no" />
|
||||
<title><%- title %></title>
|
||||
<style>
|
||||
.first-loading-wrp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 90vh;
|
||||
min-height: 90vh;
|
||||
}
|
||||
.first-loading-wrp>h1 {
|
||||
font-size: 20px;
|
||||
}
|
||||
.first-loading-wrp .loading-wrp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 98px;
|
||||
}
|
||||
.dot {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
font-size: 64px;
|
||||
transform: rotate(45deg);
|
||||
animation: antRotate 1.2s infinite linear;
|
||||
}
|
||||
.dot i {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-color:#43C9C3;
|
||||
border-radius: 100%;
|
||||
opacity: 0.5;
|
||||
transform: scale(0.75);
|
||||
transform-origin: 50% 50%;
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
}
|
||||
.dot i:nth-child(1) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.dot i:nth-child(2) {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(4) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-animation-delay: 1.2s;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
};
|
||||
h2{
|
||||
font-size: 16px!important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="first-loading-wrp">
|
||||
<div class="loading-wrp">
|
||||
<span class="dot dot-spin">
|
||||
<i></i>
|
||||
<i></i>
|
||||
<i></i>
|
||||
<i></i>
|
||||
</span>
|
||||
</div>
|
||||
<h2 style="font-size: 16px">努力加载中...</h2>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
14
jsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES6",
|
||||
"module": "commonjs",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
4380
package-lock.json
generated
Normal file
40
package.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "wxapp-home",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"test": "vite build --mode=test",
|
||||
"build": "vite build --mode=production",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nutui/nutui": "^4.1.4",
|
||||
"axios": "^1.5.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"jquery": "^3.5.1",
|
||||
"js-base64": "^3.7.7",
|
||||
"jweixin-1.6.0": "^1.0.0",
|
||||
"reset-css": "^5.0.2",
|
||||
"vant": "^4.9.17",
|
||||
"vconsole": "^3.15.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-lazyload": "^3.0.0",
|
||||
"vue-router": "^4.2.4",
|
||||
"weixin-js-sdk": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.5",
|
||||
"@vant/auto-import-resolver": "^1.2.1",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"rollup-plugin-external-globals": "^0.8.0",
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"terser": "^5.19.1",
|
||||
"unplugin-auto-import": "^0.16.7",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^4.4.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^3.2.0"
|
||||
}
|
||||
}
|
||||
1
public/vite.svg
Normal file
@ -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 |
21
src/App.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<body>
|
||||
<router-view></router-view>
|
||||
</body>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.nodata{
|
||||
width:100%;
|
||||
min-height: 300px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color:#999;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
61
src/api/user.js
Normal file
@ -0,0 +1,61 @@
|
||||
import http from '../utils/http.js'
|
||||
|
||||
const login = (data) => {
|
||||
return http.post("/login", data);
|
||||
};
|
||||
const getProjectList = (data) => {
|
||||
return http.get("/project/page", data);
|
||||
};
|
||||
const getCaseList = (data) => {
|
||||
return http.get("/case/page", data);
|
||||
};
|
||||
const getCaseDetail = (id) => {
|
||||
return http.get("/case/"+id);
|
||||
};
|
||||
const getCaseResult = (id) => {
|
||||
return http.get("/case/question/select/"+id);
|
||||
};
|
||||
|
||||
const getCommentList = (data) => {
|
||||
return http.get("/comment/page", data);
|
||||
};
|
||||
const addComment= (data) => {
|
||||
return http.post("/comment", data);
|
||||
};
|
||||
const like= (id) => {
|
||||
return http.post("/comment/like/"+id);
|
||||
};
|
||||
const cancleLike= (id) => {
|
||||
return http.del("/comment/like/"+id);
|
||||
};
|
||||
|
||||
const getScore=(data)=>{
|
||||
return http.get("/user/score",data)
|
||||
}
|
||||
const getConfig=(data)=>{
|
||||
return http.get("/project/platform",data);
|
||||
}
|
||||
const completeCase=(id,data)=>{
|
||||
return http.post("/case/finish/"+id,data,'application/json')
|
||||
}
|
||||
const behaviorRecord=(data)=>{
|
||||
return http.post("/record/user/behavior",data)
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
login,
|
||||
getProjectList,
|
||||
getCaseList,
|
||||
getCaseDetail,
|
||||
getCaseResult,
|
||||
getCommentList,
|
||||
addComment,
|
||||
like,
|
||||
cancleLike,
|
||||
getScore,
|
||||
getConfig,
|
||||
completeCase,
|
||||
behaviorRecord
|
||||
|
||||
}
|
||||
BIN
src/assets/avastar.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/banner.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
src/assets/bg.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
src/assets/cai.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
src/assets/doctor_avatar.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
src/assets/fuli.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/assets/home.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
src/assets/newicon.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
src/assets/noselect.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/nozan.png
Normal file
|
After Width: | Height: | Size: 985 B |
BIN
src/assets/result.png
Normal file
|
After Width: | Height: | Size: 573 KiB |
BIN
src/assets/select.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/titlebg.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
src/assets/top.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
src/assets/wave.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/zan.png
Normal file
|
After Width: | Height: | Size: 918 B |
118
src/components/back.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="home" @click="goHome">
|
||||
{{ source?'点击返回新医视':'点击返回首页' }}
|
||||
<!-- <div
|
||||
v-if="source==3"
|
||||
class="appbtn"
|
||||
style="
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
opacity: 0;
|
||||
"
|
||||
>
|
||||
<wx-open-launch-weapp
|
||||
:key="freshkey"
|
||||
style="
|
||||
width:94px;
|
||||
height: 30px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
"
|
||||
id="launch-btn-miniApp"
|
||||
appid="wx6e3ba63efef32cc4"
|
||||
:env-version="envVersion"
|
||||
path="pages/media_home/index"
|
||||
>
|
||||
<div v-is="'script'" type="text/wxtag-template">
|
||||
<button class="btn" style="width:100%;height:30px;position:absolute;left:0;right:0;top:0;bottom:0;">打开小程序</button>
|
||||
</div>
|
||||
</wx-open-launch-weapp>
|
||||
</div> -->
|
||||
<!-- <img src="../assets/home.png" @click="goHome" /> -->
|
||||
<!-- <img src="../assets/home.png" v-else @click="goHome"/> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, nextTick } from "vue";
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import openTag from "../utils/openTag";
|
||||
import wx from 'jweixin-1.6.0'
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
let origin=route.query.source?route.query.source:'';
|
||||
const source=ref(origin);
|
||||
const freshkey = ref(0);
|
||||
const goHome = () => {
|
||||
if(source.value==3){
|
||||
// try {
|
||||
// wx.miniProgram.navigateBack();
|
||||
// } catch (error) {
|
||||
// wx.miniProgram.switchTab({
|
||||
// url: '/pages/media_home/index'
|
||||
// })
|
||||
// }
|
||||
wx.miniProgram.switchTab({
|
||||
url: '/pages/media_home/index',
|
||||
success(res) {
|
||||
consoe.log('跳转成功');
|
||||
},
|
||||
fail(res) {
|
||||
consoe.log('跳转失败');
|
||||
}
|
||||
});
|
||||
}else{
|
||||
router.push({
|
||||
path: "/home",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
onMounted(() => {
|
||||
openTag();
|
||||
// nextTick(() => {
|
||||
// var btn = document.getElementById("launch-btn-miniApp");
|
||||
// if (btn) {
|
||||
// btn.addEventListener("launch", function (e) {
|
||||
// showToast("success");
|
||||
// freshkey.value++;
|
||||
// });
|
||||
// btn.addEventListener("error", function (e) {
|
||||
// showToast("fail", e.detail);
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.home {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
width:27px;
|
||||
padding:8px 0;
|
||||
line-height: 17px;
|
||||
top:50%;
|
||||
font-size: 14px;
|
||||
color:#fff;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 5px;
|
||||
background:#0caf98;
|
||||
flex-direction: column;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
</style>
|
||||
111
src/components/c-dialog.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<van-overlay :show="show" z-index="9999">
|
||||
<div class="wrapper">
|
||||
<div class="box">
|
||||
<div class="title">温馨提示</div>
|
||||
<div class="content">{{ message }}</div>
|
||||
<div class="foot">
|
||||
<div class="cancle" @click="cancelDialog" v-show="showCancel" >否</div>
|
||||
<div class="ok" @click="closeDialog">{{confirmText}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref} from 'vue'
|
||||
const show = ref(false);
|
||||
|
||||
const props=defineProps({
|
||||
message: {
|
||||
type: String,
|
||||
default:''
|
||||
},
|
||||
showCancel: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default:'是'
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['handledConfirm']);
|
||||
const closeDialog = () => {
|
||||
show.value = false;
|
||||
emit('handledConfirm');
|
||||
};
|
||||
const cancelDialog = () => {
|
||||
show.value = false;
|
||||
emit('handledCancel');
|
||||
};
|
||||
const openDialog = () => {
|
||||
show.value = true;
|
||||
};
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
.box {
|
||||
width: 80%;
|
||||
box-sizing: border-box;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
.title {
|
||||
font-weight: 550;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
.content {
|
||||
margin-top: 13px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
line-height: 22px;
|
||||
}
|
||||
.foot {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
.cancle {
|
||||
width: 128px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 25px;
|
||||
font-size: 16px;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.ok {
|
||||
width: 128px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background: #43C9C3;
|
||||
border-radius: 25px;
|
||||
border: 1px solid 43C9C3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
166
src/components/c-list.vue
Normal file
@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="pull_loading" @refresh="onRefresh" success-text="刷新成功">
|
||||
<van-list v-model:loading="loading" :finished="finished" finished-text="" style="min-height: 350px;" ref="clist"
|
||||
@load="onLoad" class="msglist">
|
||||
<div class="bar"></div>
|
||||
<div class="cell" v-for="(item, index) in list" :key="item.case_id" @click="goDetail(item.case_id, item.is_join)">
|
||||
<div class="namebox">
|
||||
<img src="../assets/newicon.png" alt="" v-if="item.is_new == 1">
|
||||
<img src="../assets/fuli.png" alt="" v-if="item.is_welfare == 1">
|
||||
<div class="name">{{ item.case_name }}</div>
|
||||
</div>
|
||||
<div class="btnbox">
|
||||
<div class="writer">{{ item.case_author }}</div>
|
||||
<div class="btn" :class="{ finsihed: item.is_join == 1 }">{{ item.is_join == 1 ? '已参与' : '立即参与' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nodata" v-show="list.length == 0">
|
||||
<div class="empty">
|
||||
<div class="emptydesc">
|
||||
"暂无相关数据~"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import api from '../api/user.js';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const pull_loading = ref(false);
|
||||
const page = ref(0);
|
||||
const project_id = ref(route.query.project_id);
|
||||
const list = ref([]);
|
||||
const loading = ref(false);
|
||||
const finished = ref(false);
|
||||
const props = defineProps({
|
||||
is_take_part: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
});
|
||||
|
||||
const getList = async () => {
|
||||
let { code, data } = await api.getCaseList({
|
||||
page: page.value,
|
||||
project_id: project_id.value,
|
||||
page_size: 10,
|
||||
is_take_part: props.is_take_part
|
||||
})
|
||||
loading.value = false;
|
||||
if (code == 200) {
|
||||
pull_loading.value = false;
|
||||
list.value = list.value.concat(data.data);
|
||||
if (data.data.length <10) {
|
||||
finished.value = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const onRefresh = () => {
|
||||
finished.value = false;
|
||||
loading.value = true;
|
||||
list.value = [];
|
||||
page.value = 1;
|
||||
getList()
|
||||
}
|
||||
const goDetail = (id, join) => {
|
||||
if (join == 1) {
|
||||
router.push({
|
||||
path: '/result',
|
||||
query: {
|
||||
case_id: id,
|
||||
project_id: project_id.value
|
||||
}
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: '/caseIntro',
|
||||
query: {
|
||||
case_id: id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
const onLoad = () => {
|
||||
if(!finished.value) {
|
||||
page.value++;
|
||||
getList();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
background: #F5F5F5;
|
||||
}
|
||||
|
||||
.cell {
|
||||
margin: 0 15px;
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
|
||||
.btnbox {
|
||||
margin-top: 18px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.writer {
|
||||
font-size: 15px;
|
||||
color: #666666;
|
||||
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 27px;
|
||||
background: #43C9C3;
|
||||
border-radius: 14px;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.finsihed {
|
||||
background: #B5B5B5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.namebox {
|
||||
margin-top: 15px;
|
||||
vertical-align: baseline;
|
||||
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.name {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #000000;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
line-height: 24px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
256
src/components/comment-list.vue
Normal file
@ -0,0 +1,256 @@
|
||||
<template>
|
||||
|
||||
<div class="cellbox" v-for="(item, index) in childList" :key="item.comment_id">
|
||||
<commentunit :item="item" :parentIndex="parentIndex" :index="index" :childList="childList" :parent_id="item.comment_id" :root_id="root_id" :case_id="case_id" :project_id="project_id" @freshLike="freshLike" @freshList="freshList" :replyName="replyName"></commentunit>
|
||||
<expandunit v-if="parentIndex<0 && item.case_comment && item.case_comment.length>0" :parent_id="item.comment_id" :case_id="case_id" :project_id="project_id" :total_amount="item.total_amount" @freshSecComment="freshSecComment" :index="index" :listLength="item.case_comment.length"></expandunit>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const expand = ref(true);
|
||||
const props = defineProps({
|
||||
item:{
|
||||
type:Object,
|
||||
default:()=>{}
|
||||
},
|
||||
parentIndex:{
|
||||
type:Number,
|
||||
default:-1
|
||||
},
|
||||
index:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
root_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
childList:{
|
||||
type:Array,
|
||||
default:()=>[]
|
||||
},
|
||||
parent_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
root_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
replyName:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
case_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
project_id:{
|
||||
type:String,
|
||||
default:''
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['freshLike','handleFreshList','freshSecComment']);
|
||||
const freshLike = (data) => {
|
||||
emit('freshLike',data);
|
||||
};
|
||||
const freshList = () => {
|
||||
|
||||
emit('handleFreshList',true);
|
||||
|
||||
};
|
||||
const freshSecComment = (data) => {
|
||||
emit('freshSecComment',data);
|
||||
}
|
||||
// const list=ref(props.childList);
|
||||
// const handleShowMore = () => {
|
||||
// list.value=expand.value?props.childList:props.childList.slice(0,3);
|
||||
// }
|
||||
|
||||
// watch(() =>props.childList, () => {
|
||||
// if(props.childList.length>=1 && props.parentIndex<0 ) {
|
||||
// expand.value=false;
|
||||
// handleShowMore()
|
||||
// }
|
||||
|
||||
// },{
|
||||
// immediate:true
|
||||
// });
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.cellbox {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.active {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
|
||||
.comemntcell {
|
||||
display: flex;
|
||||
|
||||
.descbox {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
// border-bottom: 1px solid #E5E5E5;
|
||||
|
||||
|
||||
.depart {
|
||||
margin-top: 10px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hospital {
|
||||
margin-top: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.date {
|
||||
margin-top: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.comemntcell {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
|
||||
.descbox {
|
||||
border: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
margin-top: 4px;
|
||||
display: flex;
|
||||
|
||||
.text {
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
line-height: 17px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 30px;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background: #43C9C3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
height: 15px;
|
||||
background: #43C9C3;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
padding: 0 4px;
|
||||
width: 52px;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.namebox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.name {
|
||||
font-size: 17px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.zanbox {
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
align-items: center;
|
||||
margin-right: 40px;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.talkbox {
|
||||
margin: 12px 30px 0px 0;
|
||||
}
|
||||
.textbox {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #43C9C3;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.toolbox {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.cancel {
|
||||
|
||||
height: 38px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #EBEBEB;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #737478;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ok {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #43C9C3;
|
||||
border: 1px solid #43C9C3;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
417
src/components/commentunit.vue
Normal file
@ -0,0 +1,417 @@
|
||||
<template>
|
||||
<div class="comemntcell">
|
||||
<van-image
|
||||
round
|
||||
width="49"
|
||||
height="49"
|
||||
:src="avatar"
|
||||
/>
|
||||
<div class="descbox">
|
||||
<div class="namebox">
|
||||
<div class="name">{{ formatName(item.user_name) }}</div>
|
||||
<div
|
||||
class="zanbox"
|
||||
@click="toggleLike(item.comment_id, item.is_like, index)"
|
||||
>
|
||||
<img src="../assets/nozan.png" alt="" v-if="!item.is_like" />
|
||||
<img src="../assets/zan.png" alt="" v-else />
|
||||
<div class="num" v-if="item.like_num > 0">{{ formatNumber(item.like_num) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="depart">{{ item.department_name }}</div>
|
||||
<div class="hospital">{{ item.hospital_name }}</div>
|
||||
<div class="date">{{ formateDate(item.created_at) }}</div>
|
||||
<div class="tag" v-if="item.is_high_quality == 1">
|
||||
<span>优质解答</span>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<div class="text">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
<div class="reply" @click="openConmment(item.level, item.user_name)">
|
||||
{{ item.level == 1 ? "回复" : "评论" }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <reply ref="replyRef" :parentIndex="parentIndex" :parent_id='item.comment_id' :root_id="''" :case_id="case_id" :project_id="project_id"></reply> -->
|
||||
<div class="talkbox" v-show="showReply">
|
||||
<div class="textbox">
|
||||
<van-field
|
||||
:autosize="{ minHeight: 120 }"
|
||||
v-model="content"
|
||||
rows="2"
|
||||
autosize
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
placeholder="请输入评论内容"
|
||||
show-word-limit
|
||||
/>
|
||||
</div>
|
||||
<div class="toolbox">
|
||||
<div class="cancel" @click="showReply = false">取消</div>
|
||||
<button class="ok" @click="handleAdd" :disabled="isLock">提交</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sondiv">
|
||||
<comment-list
|
||||
v-if="item.case_comment && item.case_comment.length > 0"
|
||||
:childList="item.case_comment"
|
||||
:parentIndex="index"
|
||||
@freshLike="freshLike"
|
||||
:root_id="parent_id"
|
||||
:replyName="item.user_name"
|
||||
:case_id="case_id"
|
||||
:project_id="project_id"
|
||||
@freshSecComment="freshSecComment"
|
||||
@handleFreshList="handleFreshList"
|
||||
></comment-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { showToast } from "vant";
|
||||
import { ref } from "vue";
|
||||
import api from "../api/user.js";
|
||||
import dayjs from "dayjs";
|
||||
import avatar from "../assets/doctor_avatar.png";
|
||||
|
||||
const replyRef = ref(null);
|
||||
const showReply = ref(false);
|
||||
const content = ref("");
|
||||
const level = ref(2);
|
||||
const writer = ref("");
|
||||
const isLock = ref(false);
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
parent_id: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
root_id: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
replyName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
childList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
project_id: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
case_id: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
|
||||
parentIndex: {
|
||||
type: Number,
|
||||
default: -1,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits([
|
||||
"freshLike",
|
||||
"freshList",
|
||||
"freshSecComment",
|
||||
"handleFreshList",
|
||||
]);
|
||||
|
||||
const formateDate = (val) => {
|
||||
return dayjs(val).format("YYYY-MM-DD HH:mm");
|
||||
};
|
||||
|
||||
/**
|
||||
* 显示回复框的处理函数
|
||||
*
|
||||
* 该函数用于设置 showReply 的值为 true,从而显示回复框。
|
||||
*/
|
||||
const handleReply = () => {
|
||||
replyRef.value[0].openReply();
|
||||
};
|
||||
|
||||
const handleLike = async (id, index) => {
|
||||
const { code } = await api.like(id);
|
||||
if (code == 200) {
|
||||
showToast("点赞成功");
|
||||
emit("freshLike", {
|
||||
parentIndex: props.parentIndex,
|
||||
index: index,
|
||||
likeNum: 1,
|
||||
});
|
||||
}
|
||||
};
|
||||
const freshLike = (data) => {
|
||||
emit("freshLike", data);
|
||||
};
|
||||
const freshSecComment = (data) => {
|
||||
emit("freshSecComment", data);
|
||||
};
|
||||
const handleCancleLike = async (id, index) => {
|
||||
const { code } = await api.cancleLike(id);
|
||||
if (code == 200) {
|
||||
showToast("取消点赞成功");
|
||||
emit("freshLike", {
|
||||
parentIndex: props.parentIndex,
|
||||
index: index,
|
||||
likeNum: -1,
|
||||
});
|
||||
}
|
||||
};
|
||||
const toggleLike = (id, flag, index) => {
|
||||
console.log(id, flag, props.parentIndex, index);
|
||||
if (flag) {
|
||||
handleCancleLike(id, index);
|
||||
} else {
|
||||
handleLike(id, index);
|
||||
}
|
||||
};
|
||||
const formatNumber = (value) => {
|
||||
if (value > 9999) {
|
||||
return (value / 10000).toFixed(1) + "w";
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
const formatName=(val)=>{
|
||||
if(!val) return '医生'
|
||||
return val.slice(0,1)+'医生'
|
||||
|
||||
}
|
||||
const openConmment = (flag, name) => {
|
||||
showReply.value = true;
|
||||
if (flag == 2 || flag == 3) {
|
||||
content.value = "@" + formatName(name) + ":";
|
||||
writer.value = "@" + formatName(name) + ":";
|
||||
level.value = 3;
|
||||
} else {
|
||||
content.value = "";
|
||||
writer.value = "";
|
||||
level.value = 2;
|
||||
}
|
||||
};
|
||||
const handleAdd = async () => {
|
||||
if (content.value == "" || content.value == writer.value) {
|
||||
showToast("请输入内容");
|
||||
return false;
|
||||
}
|
||||
showReply.value = false;
|
||||
isLock.value = true;
|
||||
const { code, data } = await api.addComment({
|
||||
case_id: props.case_id,
|
||||
project_id: props.project_id,
|
||||
content: content.value,
|
||||
level: level.value,
|
||||
root_id: level.value == 2 ? props.parent_id : props.root_id,
|
||||
parent_id: props.parent_id,
|
||||
});
|
||||
isLock.value = false;
|
||||
if (code == 200) {
|
||||
emit("freshList");
|
||||
content.value = "";
|
||||
}
|
||||
};
|
||||
const handleFreshList = () => {
|
||||
emit("freshList");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.sondiv {
|
||||
margin-top: 15px;
|
||||
:deep() .cellbox {
|
||||
padding-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.cellbox {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.comemntcell {
|
||||
display: flex;
|
||||
|
||||
.descbox {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
// border-bottom: 1px solid #E5E5E5;
|
||||
|
||||
.depart {
|
||||
margin-top: 10px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hospital {
|
||||
margin-top: 5px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.date {
|
||||
margin-top: 5px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.comemntcell {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
|
||||
.descbox {
|
||||
border: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
line-height: 17px;
|
||||
flex: 1;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 30px;
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
background: #43c9c3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
height: 15px;
|
||||
background: #43c9c3;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
padding: 0 4px;
|
||||
width: 52px;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.namebox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.name {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.zanbox {
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
justify-content: flex-end;
|
||||
color: #333333;
|
||||
align-items: center;
|
||||
margin-right: 40px;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.expand {
|
||||
width: 240px;
|
||||
height: 19px;
|
||||
margin: 12px auto 12px;
|
||||
background: #43c9c3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.talkbox {
|
||||
margin: 12px 30px 0px 0;
|
||||
}
|
||||
.textbox {
|
||||
border-radius: 5px;
|
||||
border: 0.5px solid #43c9c3;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.toolbox {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.cancel {
|
||||
height: 38px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #737478;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ok {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #43c9c3;
|
||||
border: 1px solid #43c9c3;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
82
src/components/expandunit.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="expand" @click="showMore" v-if="restNum>0">
|
||||
展示剩余({{restNum}})条回复
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import api from '../api/user.js';
|
||||
const page=ref(1);
|
||||
const props = defineProps({
|
||||
parent_id:{
|
||||
type:String,
|
||||
default:'',
|
||||
},
|
||||
index:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
case_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
project_id:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
listLength:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
total_amount:{
|
||||
type:Number,
|
||||
default:0
|
||||
}
|
||||
})
|
||||
const restNum=ref(props.total_amount);
|
||||
const emit = defineEmits(['freshSecComment']);
|
||||
const showMore=()=>{
|
||||
page.value++;
|
||||
getList(props.parent_id)
|
||||
}
|
||||
const getList = async (root_id='') => {
|
||||
const { code, data } = await api.getCommentList({
|
||||
case_id:props.case_id,
|
||||
project_id:props.project_id,
|
||||
page:page.value,
|
||||
page_size:5,
|
||||
root_id:root_id
|
||||
})
|
||||
if (code == 200) {
|
||||
if(data.data.length>0){
|
||||
emit('freshSecComment',{
|
||||
commentIndex:props.index,
|
||||
commentData:data.data
|
||||
});
|
||||
nextTick(()=>{
|
||||
restNum.value=data.total-props.listLength;
|
||||
})
|
||||
|
||||
}
|
||||
//console.log(data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.expand {
|
||||
width: 240px;
|
||||
height: 19px;
|
||||
margin: 12px auto 12px;
|
||||
background: #43C9C3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
</style>
|
||||
28
src/components/loading/index.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { createApp } from "vue"
|
||||
|
||||
// 导入写好的Loading.vue文件
|
||||
import Loading from "./loading.vue"
|
||||
|
||||
export default {
|
||||
loading: null,
|
||||
// 每当这个插件被添加到应用程序中时,如果它是一个对象,就会调用 install 方法。如果它是一个 function,则函数本身将被调用。在这两种情况下——它都会收到两个参数:由 Vue 的 createApp 生成的 app 对象和用户传入的选项。
|
||||
install(app) {
|
||||
if (this.loading) {
|
||||
// 防止多次载入
|
||||
app.config.globalProperties.$loading = this.loading
|
||||
return
|
||||
}
|
||||
// 创建Loading实例,用于挂载
|
||||
let instance = createApp(Loading)
|
||||
// 创建div元素装载Loading对象
|
||||
let div = document.createElement("div")
|
||||
div.setAttribute("id","maskbox")
|
||||
let body = document.body
|
||||
// 导入body中
|
||||
body.appendChild(div);
|
||||
|
||||
this.loading = instance.mount(div)
|
||||
// 挂载vue身上
|
||||
app.config.globalProperties.$loading = this.loading;
|
||||
}
|
||||
}
|
||||
194
src/components/loading/loading.vue
Normal file
@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="maskbox" v-if="loading">
|
||||
<div class="mask"></div>
|
||||
<div class="sk-fading-circle">
|
||||
<div class="sk-circle1 sk-circle"></div>
|
||||
<div class="sk-circle2 sk-circle"></div>
|
||||
<div class="sk-circle3 sk-circle"></div>
|
||||
<div class="sk-circle4 sk-circle"></div>
|
||||
<div class="sk-circle5 sk-circle"></div>
|
||||
<div class="sk-circle6 sk-circle"></div>
|
||||
<div class="sk-circle7 sk-circle"></div>
|
||||
<div class="sk-circle8 sk-circle"></div>
|
||||
<div class="sk-circle9 sk-circle"></div>
|
||||
<div class="sk-circle10 sk-circle"></div>
|
||||
<div class="sk-circle11 sk-circle"></div>
|
||||
<div class="sk-circle12 sk-circle"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const loading = ref(false)
|
||||
const show = () => {
|
||||
loading.value = true
|
||||
}
|
||||
const hide = () => {
|
||||
loading.value = false
|
||||
}
|
||||
defineExpose({
|
||||
show,
|
||||
hide
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.maskbox{
|
||||
top:0;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
z-index:9990;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.mask{
|
||||
top:0;
|
||||
bottom:0;
|
||||
position: absolute;
|
||||
width:100%;
|
||||
height:100%;
|
||||
opacity: 0.4;
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
.sk-fading-circle {
|
||||
margin: 100px auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sk-fading-circle .sk-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sk-fading-circle .sk-circle:before {
|
||||
content: '';
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 15%;
|
||||
height: 15%;
|
||||
background-color: #fff;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;
|
||||
animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;
|
||||
}
|
||||
.sk-fading-circle .sk-circle2 {
|
||||
-webkit-transform: rotate(30deg);
|
||||
-ms-transform: rotate(30deg);
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle3 {
|
||||
-webkit-transform: rotate(60deg);
|
||||
-ms-transform: rotate(60deg);
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle4 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle5 {
|
||||
-webkit-transform: rotate(120deg);
|
||||
-ms-transform: rotate(120deg);
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle6 {
|
||||
-webkit-transform: rotate(150deg);
|
||||
-ms-transform: rotate(150deg);
|
||||
transform: rotate(150deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle7 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle8 {
|
||||
-webkit-transform: rotate(210deg);
|
||||
-ms-transform: rotate(210deg);
|
||||
transform: rotate(210deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle9 {
|
||||
-webkit-transform: rotate(240deg);
|
||||
-ms-transform: rotate(240deg);
|
||||
transform: rotate(240deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle10 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
-ms-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle11 {
|
||||
-webkit-transform: rotate(300deg);
|
||||
-ms-transform: rotate(300deg);
|
||||
transform: rotate(300deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle12 {
|
||||
-webkit-transform: rotate(330deg);
|
||||
-ms-transform: rotate(330deg);
|
||||
transform: rotate(330deg);
|
||||
}
|
||||
.sk-fading-circle .sk-circle2:before {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle3:before {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle4:before {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle5:before {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle6:before {
|
||||
-webkit-animation-delay: -0.7s;
|
||||
animation-delay: -0.7s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle7:before {
|
||||
-webkit-animation-delay: -0.6s;
|
||||
animation-delay: -0.6s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle8:before {
|
||||
-webkit-animation-delay: -0.5s;
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle9:before {
|
||||
-webkit-animation-delay: -0.4s;
|
||||
animation-delay: -0.4s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle10:before {
|
||||
-webkit-animation-delay: -0.3s;
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle11:before {
|
||||
-webkit-animation-delay: -0.2s;
|
||||
animation-delay: -0.2s;
|
||||
}
|
||||
.sk-fading-circle .sk-circle12:before {
|
||||
-webkit-animation-delay: -0.1s;
|
||||
animation-delay: -0.1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-circleFadeDelay {
|
||||
0%, 39%, 100% { opacity: 0; }
|
||||
40% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes sk-circleFadeDelay {
|
||||
0%, 39%, 100% { opacity: 0; }
|
||||
40% { opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
207
src/components/question.vue
Normal file
@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<div class="qbox">
|
||||
<div class="title">{{question.question_name}}({{question.question_type==1?'单选':question.question_type==2?'多选':question.question_type==3?'问答':'判断' }})</div>
|
||||
<div class="tips" v-if="question.question_type==2">注:本题可选择多个选项!</div>
|
||||
<div class="tips" v-else-if="question.question_type==1">注:本题最多可选择1个选项!</div>
|
||||
<div class="options" v-if="question.question_type==2">
|
||||
<van-checkbox-group v-model="manychecked" @change="changeCheck" :disabled="disabled">
|
||||
<div class="cell" v-for="(item,index) in question.case_item_question_option" :key="item.option_id">
|
||||
<van-checkbox :name="zimu[index]">
|
||||
{{ item.option_value }}
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-checkbox>
|
||||
</div>
|
||||
<!-- <div class="cell">
|
||||
<van-checkbox name="b">
|
||||
复选框 b
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-checkbox>
|
||||
</div> -->
|
||||
</van-checkbox-group>
|
||||
</div>
|
||||
<div class="options" v-else-if="question.question_type==1" >
|
||||
<van-radio-group v-model="singlechecked" @change="changeRadio" :disabled="disabled">
|
||||
<div class="cell" v-for="(item,index) in question.case_item_question_option" :key="item.option_id">
|
||||
<van-radio :name="zimu[index]">
|
||||
{{ item.option_value }}
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-radio>
|
||||
</div>
|
||||
</van-radio-group>
|
||||
</div>
|
||||
<div class="options_con" v-else-if="question.question_type == 3">
|
||||
<van-field @update:model-value="changeContent" :autosize="{ minHeight: 120 }" v-model="content" rows="2" autosize type="textarea"
|
||||
placeholder="请输入内容" show-word-limit />
|
||||
</div>
|
||||
<div class="options" v-else-if="question.question_type == 4">
|
||||
<van-radio-group v-model="singlechecked" @change="changeRadio" :disabled="disabled">
|
||||
<div class="cell" v-for="(item,index) in question.case_item_question_option" :key="item.option_id">
|
||||
<van-radio :name="zimu[index]">
|
||||
{{ item.option_value }}
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-radio>
|
||||
</div>
|
||||
</van-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import activeIcon from "@/assets/select.png";
|
||||
import inactiveIcon from "@/assets/noselect.png";
|
||||
const emit = defineEmits(['checkAnswer']);
|
||||
const manychecked = ref([]);
|
||||
const singlechecked = ref('');
|
||||
const content = ref('')
|
||||
const zimu=['A','B','C','D','E','F','G','H','I','J'];
|
||||
const props=defineProps({
|
||||
question: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
pageIndex:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
questionIndex:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
});
|
||||
const changeRadio = (val) => {
|
||||
let optionObj=props.question.case_item_question_option.find((item,index)=>zimu[index]==val);
|
||||
emit('checkAnswer',{
|
||||
pageIndex:props.pageIndex,
|
||||
answer:val,
|
||||
questionId:props.question.question_id,
|
||||
error_tips:props.question.error_tips,
|
||||
is_right_next:props.question.is_right_next,
|
||||
option_id:optionObj?optionObj.option_id:'',
|
||||
questionIndex:props.questionIndex,
|
||||
question_type:props.question.question_type,
|
||||
question_name:props.question.question_name,
|
||||
question_answer:props.question.question_answer
|
||||
})
|
||||
|
||||
};
|
||||
const changeContent = (val) => {
|
||||
|
||||
emit('checkAnswer',{
|
||||
pageIndex:props.pageIndex,
|
||||
answer:val,
|
||||
error_tips:props.question.error_tips,
|
||||
questionId:props.question.question_id,
|
||||
is_right_next:props.question.is_right_next,
|
||||
questionIndex:props.questionIndex,
|
||||
question_type:props.question.question_type,
|
||||
question_name:props.question.question_name,
|
||||
question_answer:props.question.question_answer
|
||||
})
|
||||
};
|
||||
const changeCheck = (val) => {
|
||||
let sortAnswer=val.sort();
|
||||
let option_id='';
|
||||
for(let i=0;i<sortAnswer.length;i++){
|
||||
let optionObj=props.question.case_item_question_option.find((item,index)=>zimu[index]==sortAnswer[i]);
|
||||
if(option_id){
|
||||
if(optionObj.option_id){
|
||||
option_id+=','+optionObj.option_id;
|
||||
}
|
||||
}else{
|
||||
if(optionObj.option_id){
|
||||
option_id=optionObj.option_id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//let optionObj=props.question.case_item_question_option.find((item,index)=>zimu[index]==val);
|
||||
emit('checkAnswer',{
|
||||
pageIndex:props.pageIndex,
|
||||
answer:sortAnswer,
|
||||
option_id:option_id,
|
||||
is_right_next:props.question.is_right_next,
|
||||
error_tips:props.question.error_tips,
|
||||
questionId:props.question.question_id,
|
||||
questionIndex:props.questionIndex,
|
||||
question_type:props.question.question_type,
|
||||
question_name:props.question.question_name,
|
||||
question_answer:props.question.question_answer
|
||||
|
||||
|
||||
})
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.options_con {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #B8B8B8;
|
||||
margin-top: 15px;
|
||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 15px 0px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.qbox {
|
||||
margin-bottom: 15px;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cell {
|
||||
border-radius: 10px;
|
||||
border: 1px solid #B8B8B8;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.active{
|
||||
border: 1px solid #43C9C3;
|
||||
}
|
||||
|
||||
.cell:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 15px;
|
||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 15px 12px;
|
||||
}
|
||||
.img-icon{
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
163
src/components/questionend.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div class="qbox" v-if="question.question_type != 3">
|
||||
<div class="title">
|
||||
{{ question.question_name }}({{ question.question_type == 1 ? '单选' : question.question_type == 2 ? '多选' :question.question_type == 3 ? '问答' : '判断'}})</div>
|
||||
<div class="tips" v-if="question.question_type == 2">注:本题可选择多个选项!</div>
|
||||
<div class="tips" v-else-if="question.question_type == 1">注:本题最多可选择1个选项!</div>
|
||||
<div class="options" v-if="question.question_type == 1 || question.question_type == 2 || question.question_type == 4">
|
||||
|
||||
<div class="cell" v-for="(item, index) in question.case_item_question_option" :key="item.option_id" v-if="question.case_item_question_option">
|
||||
<div class="title">{{ item.option_value }}</div>
|
||||
<div class="progressbox">
|
||||
<div class="progress">
|
||||
<div class="inner" :style="{ width: 220 / 100 * item.proportion + 'px' }"></div>
|
||||
</div>
|
||||
<div class="numbox">
|
||||
<div class="num">{{ item.select_num }}票</div>
|
||||
<div class="precent">{{ item.proportion }}%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options_con" v-if="question.question_type == 3">
|
||||
<van-field readonly :autosize="{ minHeight: 120 }" v-model="question.question_answer" rows="2" autosize type="textarea"
|
||||
placeholder="请输入内容" show-word-limit />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const emit = defineEmits(['checkAnswer']);
|
||||
const zimu = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
|
||||
const props = defineProps({
|
||||
question: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
questionIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.options_con {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #efefef;
|
||||
margin-top: 15px;
|
||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 15px 0px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.qbox {
|
||||
margin-bottom: 15px;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cell {
|
||||
border-bottom: 1px solid #efefef;
|
||||
background: #fff;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.title {
|
||||
margin: 0 10px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #1F1F1F;
|
||||
}
|
||||
|
||||
.numbox {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
|
||||
.precent {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.progressbox {
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 8px 10px 15px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
|
||||
border-radius: 5px;
|
||||
|
||||
.progress {
|
||||
margin-right: 10px;
|
||||
width: 220px;
|
||||
overflow: hidden;
|
||||
height: 5px;
|
||||
background: #EFF3FF;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: 80%;
|
||||
height: 5px;
|
||||
border-radius: 5px;
|
||||
background: #43C9C3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1px solid #43C9C3;
|
||||
}
|
||||
|
||||
.cell:last-child {
|
||||
margin-bottom: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 15px;
|
||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 15px 0px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.img-icon {
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
103
src/components/reply.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="talkbox " v-show="showReply">
|
||||
<div class="textbox">
|
||||
<van-field :autosize="{ minHeight: 120 }" v-model="content" rows="2" autosize type="textarea"
|
||||
maxlength="200" placeholder="请输入评论内容" show-word-limit />
|
||||
|
||||
</div>
|
||||
<div class="toolbox">
|
||||
<div class="cancel" @click="showReply = false">取消</div>
|
||||
<div class="ok" @click="handleSubmit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const showReply=ref(false);
|
||||
const content=ref('')
|
||||
const props = defineProps({
|
||||
root_id: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
project_id:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
case_id:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parent_id: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
});
|
||||
const handleSubmit=()=>{
|
||||
showReply.value=false;
|
||||
};
|
||||
const openReply=()=>{
|
||||
showReply.value=true;
|
||||
};
|
||||
const closeReply=()=>{
|
||||
showReply.value=false;
|
||||
};
|
||||
defineExpose({
|
||||
openReply,
|
||||
closeReply
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.talkbox {
|
||||
margin: 12px 30px 0px 0;
|
||||
}
|
||||
.textbox {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #43C9C3;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.toolbox {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.cancel {
|
||||
|
||||
height: 38px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #EBEBEB;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #737478;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ok {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #43C9C3;
|
||||
border: 1px solid #43C9C3;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
76
src/components/singleQuestion.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="qbox">
|
||||
<div class="title">结合患者目前情况,下一步该如何治疗?</div>
|
||||
<div class="tips">注:本题可选择多个选项!</div>
|
||||
<div class="options">
|
||||
<van-radio-group v-model="checked">
|
||||
<div class="cell">
|
||||
<van-radio name="a">
|
||||
复选框 a
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-radio>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<van-radio name="b">
|
||||
复选框 b
|
||||
<template #icon="props">
|
||||
<img class="img-icon" :src="props.checked ? activeIcon : inactiveIcon" />
|
||||
</template>
|
||||
</van-radio>
|
||||
</div>
|
||||
</van-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import activeIcon from "@/assets/select.png";
|
||||
import inactiveIcon from "@/assets/noselect.png";
|
||||
const checked = ref('');
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.qbox {
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.cell {
|
||||
border-radius: 10px;
|
||||
border: 1px solid #B8B8B8;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.active{
|
||||
border: 1px solid #43C9C3;
|
||||
}
|
||||
|
||||
.cell:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 15px;
|
||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 10px;
|
||||
padding: 15px 12px;
|
||||
}
|
||||
.img-icon{
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
892
src/components/topicList.vue
Normal file
@ -0,0 +1,892 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="pull_loading" @refresh="onRefresh" success-text="刷新成功">
|
||||
<van-list
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text=""
|
||||
ref="list"
|
||||
@load="onLoad"
|
||||
class="msglist"
|
||||
>
|
||||
<div
|
||||
class="msgcell"
|
||||
v-for="(item, index) in list"
|
||||
:key="item.gandanhome_id"
|
||||
>
|
||||
<div class="namebox">
|
||||
<div class="left">
|
||||
<div class="leftcon">
|
||||
<img
|
||||
v-lazy="img_host + item.patient_photo"
|
||||
alt=""
|
||||
class="avastar head"
|
||||
@click="goPage(item.patient_uuid)"
|
||||
/>
|
||||
<div class="info">
|
||||
<div class="name_level">
|
||||
<div class="name">{{ item.patient_name }}</div>
|
||||
<img
|
||||
v-lazy="imgcell.url"
|
||||
alt=""
|
||||
class="level"
|
||||
v-for="imgcell in item.tags"
|
||||
:key="imgcell.url"
|
||||
v-if="type != 'mypage'"
|
||||
/>
|
||||
<div
|
||||
class="settop"
|
||||
v-if="type == 'mypage'|| type =='patient'"
|
||||
v-show="item.top_flag == 1"
|
||||
>
|
||||
<span>置顶</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="time">{{ item.update_date | fromTimeNow }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="more"
|
||||
v-if="type == 'mypage'"
|
||||
@click="openMore(index, item.gandanhome_id, item.top_flag)"
|
||||
>
|
||||
...
|
||||
</div>
|
||||
</div>
|
||||
<div class="title" @click="goDetail(item.gandanhome_id)">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<!-- <div @click.stop="goDetail(item.gandanhome_id)"> -->
|
||||
<clamp
|
||||
:htmlContent="item.content"
|
||||
:topics="item.topics"
|
||||
:id="item.gandanhome_id"
|
||||
></clamp>
|
||||
<!-- </div> -->
|
||||
<div
|
||||
class="imgbox"
|
||||
@click="goDetail(item.gandanhome_id)"
|
||||
v-if="item.imgs.length <= 6 && item.imgs.length != 4"
|
||||
>
|
||||
<div class="imgrow" v-for="itemcell in transforPages(item.imgs, 3)">
|
||||
<div class="imgcell" v-for="imgcell in itemcell">
|
||||
<van-image
|
||||
v-if="imgcell.status==1"
|
||||
lazy-load
|
||||
fit="cover"
|
||||
radius="8px"
|
||||
:src="imgcell.url"
|
||||
width="110px"
|
||||
height="110px"
|
||||
/>
|
||||
<van-image
|
||||
v-else
|
||||
lazy-load
|
||||
fit="cover"
|
||||
radius="8px"
|
||||
:src="require('../assets/weigui.png')"
|
||||
width="110px"
|
||||
height="110px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="imgbox" v-else-if="item.imgs.length == 4">
|
||||
<div
|
||||
class="imgrow tworow"
|
||||
v-for="itemcell in transforPages(item.imgs, 2)"
|
||||
@click="goDetail(item.gandanhome_id)"
|
||||
>
|
||||
<div class="imgcell" v-for="imgcell in itemcell">
|
||||
<van-image
|
||||
lazy-load
|
||||
v-if="imgcell.status==1"
|
||||
radius="8px"
|
||||
:src="imgcell.url"
|
||||
width="110px"
|
||||
height="110px"
|
||||
/>
|
||||
<van-image
|
||||
lazy-load
|
||||
v-else
|
||||
radius="8px"
|
||||
:src="require('../assets/weigui.png')"
|
||||
width="110px"
|
||||
height="110px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="imgbox" v-else>
|
||||
<div class="swiperbox">
|
||||
<van-swipe :height="142" indicator-color="#3CC7C0">
|
||||
<van-swipe-item
|
||||
v-for="(imgcell, index) in item.imgs"
|
||||
:key="index"
|
||||
|
||||
@click="goDetail(item.gandanhome_id)"
|
||||
>
|
||||
<div class="swipebg" >
|
||||
<img v-lazy="imgcell.url" alt="" class="swiperImg" v-if="imgcell.status==1"/>
|
||||
<img src="../assets/weigui.png" alt="" class="swiperImg" v-else>
|
||||
</div>
|
||||
|
||||
<!-- <img v-lazy="imgcell.url" alt="" class="swipebg" v-if="imgcell.status==1"/>
|
||||
<img src="../assets/weigui.png" alt="" class="swipebg" v-else> -->
|
||||
<img v-lazy="imgcell.url" alt="" class="swiperImg" v-if="imgcell.status==1"/>
|
||||
<img src="../assets/weigui.png" alt="" class="swiperImg" v-else>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tool" @click="goDetail(item.gandanhome_id)">
|
||||
<div class="address">
|
||||
{{ item.ip_show == 1 ? item.ip_address_province : "" }}
|
||||
</div>
|
||||
<div class="zan_comment">
|
||||
<div
|
||||
class="zan"
|
||||
@click.stop="
|
||||
toggleLike(item.isLike, index, item.gandanhome_id, item.likeNum)
|
||||
"
|
||||
>
|
||||
<img src="../assets/zan.png" alt="" v-if="item.isLike == 1" />
|
||||
<img src="../assets/unzan.png" alt="" v-else />
|
||||
<div class="zancount" v-if="item.likeNum >0">{{ item.likeNum }}</div>
|
||||
</div>
|
||||
<!-- <div class="collectbox" v-if="type=='mypage' || type=='mycollect'" @click.stop="toggleCollect(item.is_collect,index,item.gandanhome_id)">
|
||||
|
||||
<img src="../assets/collect.png" alt="" v-if="item.is_collect == 1"/>
|
||||
<img src="../assets/uncollect.png" alt="" v-else />
|
||||
</div> -->
|
||||
<div class="comment">
|
||||
<img src="../assets/msg_comment.png" alt="" />
|
||||
<div class="zancount" v-if="item.commonNum >0">{{ item.commonNum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nodata" v-show="list.length == 0 ">
|
||||
<div class="empty">
|
||||
<img src="../assets/tie_empty.png" alt="" />
|
||||
<div class="emptydesc">
|
||||
{{
|
||||
type == "searchBytitle"
|
||||
? "暂未搜到相关帖子~"
|
||||
: type == "homeFollow"
|
||||
? "关注的人暂无发布哦~"
|
||||
: type == "homeFriend"
|
||||
? "好友暂无发布哦~"
|
||||
: "暂无相关帖子~"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-popup
|
||||
v-model:show="showBottom"
|
||||
round
|
||||
position="bottom"
|
||||
:style="{ height: '236px' }"
|
||||
>
|
||||
<div class="dealcell" @click="toggleTop">
|
||||
{{ top_flag == 0 ? "置顶" : "取消置顶" }}
|
||||
</div>
|
||||
<div class="dealcell" @click="goPublic">编辑</div>
|
||||
<div class="dealcell" @click="confirmDel">删除</div>
|
||||
<div class="ba"></div>
|
||||
<div class="dealcell" @click="showBottom = false">取消</div>
|
||||
</van-popup>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import img_host from "@/utils/imgHost";
|
||||
import clamp from "./clamp";
|
||||
import moment from "moment";
|
||||
import { Dialog } from "vant";
|
||||
import { throttle } from "../utils/debounce";
|
||||
import cookie from "../utils/cookie";
|
||||
moment.locale("zh-cn");
|
||||
export default {
|
||||
components: {
|
||||
clamp,
|
||||
},
|
||||
filters: {
|
||||
fromTimeNow(val) {
|
||||
return moment(val).fromNow();
|
||||
},
|
||||
},
|
||||
mounted(){
|
||||
|
||||
this.$toast.allowMultiple();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
img_host: img_host,
|
||||
finished: false,
|
||||
loading: false,
|
||||
pull_loading: false,
|
||||
page: 0,
|
||||
list: [],
|
||||
top_flag: 0,
|
||||
showBottom: false,
|
||||
dealIndex: 0,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
keyWord: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
patient_uuid: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
topic_id:{
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
api: {
|
||||
type: Function,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
keyWord(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
if(this.type == "searchBytitle"){
|
||||
this.freshList();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeBottom(){
|
||||
this.showBottom = false;
|
||||
},
|
||||
goPage(uuid) {
|
||||
let cur_uuid = cookie.readCookie("patient_uuid");
|
||||
if (uuid == cur_uuid) {
|
||||
this.$router.push({
|
||||
path: "/mypage",
|
||||
});
|
||||
} else {
|
||||
this.$router.push({
|
||||
path: "/patientpage",
|
||||
query: {
|
||||
patient_uuid: uuid,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
confirmDel() {
|
||||
this.showBottom = false;
|
||||
Dialog.confirm({
|
||||
title: "温馨提示",
|
||||
className: "mydialog",
|
||||
message: "是否删除该帖子?",
|
||||
})
|
||||
.then(() => {
|
||||
this.handelDelTopic();
|
||||
})
|
||||
.catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
},
|
||||
openMore(index, gandanhome_id, top_flag) {
|
||||
this.top_flag = top_flag;
|
||||
this.gandanhome_id = gandanhome_id;
|
||||
this.dealIndex = index;
|
||||
this.showBottom = true;
|
||||
},
|
||||
toggleTop() {
|
||||
this.top_flag == 0 ? this.handleTop() : this.handleCancelTop();
|
||||
this.showBottom = false;
|
||||
},
|
||||
goPublic() {
|
||||
this.showBottom = false;
|
||||
this.$router.push({
|
||||
path: "/publish",
|
||||
query: {
|
||||
gandanhome_id: this.gandanhome_id,
|
||||
},
|
||||
});
|
||||
},
|
||||
handelDelTopic() {
|
||||
this.$api
|
||||
.delTopic({
|
||||
gandanhome_id: this.gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.list.splice(this.dealIndex, 1);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "删除成功",
|
||||
});
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleTop() {
|
||||
this.$api
|
||||
.setTop({
|
||||
gandanhome_id: this.gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[this.dealIndex], "top_flag", 1);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "置顶成功",
|
||||
});
|
||||
this.freshList();
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleCompleteTask(id) {
|
||||
this.$api
|
||||
.addGrowRecord({
|
||||
task_unique_id: id,
|
||||
})
|
||||
.then((rep) => {
|
||||
var result = rep.data;
|
||||
if (result.code == 200) {
|
||||
if(result.data){
|
||||
this.$toast({
|
||||
duration: 2000,
|
||||
message:'成长值+1',
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
handleCancelTop() {
|
||||
this.$api
|
||||
.cancelSetTop({
|
||||
gandanhome_id: this.gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[this.dealIndex], "top_flag", 0);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "已取消置顶",
|
||||
});
|
||||
this.freshList();
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onLoad() {
|
||||
if (this.type == "searchBytitle") {
|
||||
let str = this.keyWord.replace(/\s+/g, "");
|
||||
if (str == "") {
|
||||
this.page = 1;
|
||||
this.list = [];
|
||||
this.loading = false;
|
||||
this.finished = false;
|
||||
// this.$toast({
|
||||
// duration: 1000,
|
||||
// message: '请输入搜索内容',
|
||||
// });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.page++;
|
||||
this.handleList();
|
||||
},
|
||||
goDetail(id) {
|
||||
this.$router.push({
|
||||
path: "talkDetail",
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
},
|
||||
onRefresh(){
|
||||
this.freshList()
|
||||
},
|
||||
freshList: throttle(function () {
|
||||
if (this.type == "searchBytitle") {
|
||||
if (this.keyWord.replace(/\s+/g, "") == "") {
|
||||
this.page = 1;
|
||||
this.list = [];
|
||||
this.loading = false;
|
||||
this.finished = false;
|
||||
// this.$toast({
|
||||
// duration: 1000,
|
||||
// message: '请输入搜索内容',
|
||||
// });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.page = 1;
|
||||
this.pull_loading=false
|
||||
this.list = [];
|
||||
this.loading = false;
|
||||
this.finished = false;
|
||||
this.handleList();
|
||||
}, 500),
|
||||
handleList() {
|
||||
let jsonData = null;
|
||||
if (this.type == "searchBytitle") {
|
||||
if (this.keyWord.replace(/\s+/g, "") == "") {
|
||||
this.page = 1;
|
||||
this.list = [];
|
||||
this.loading = false;
|
||||
this.finished = false;
|
||||
// this.$toast({
|
||||
// duration: 1000,
|
||||
// message: '请输入搜索内容',
|
||||
// });
|
||||
return false;
|
||||
}
|
||||
jsonData = {
|
||||
type: 1,
|
||||
keyWord: this.keyWord,
|
||||
page: this.page,
|
||||
page_size: 10,
|
||||
};
|
||||
}else if(this.type =='ralationTopic'){
|
||||
jsonData = {
|
||||
topic_id: this.topic_id,
|
||||
page: this.page,
|
||||
page_size: 10,
|
||||
};
|
||||
} else if (this.type == "patient") {
|
||||
jsonData = {
|
||||
patient_uuid: this.patient_uuid,
|
||||
page: this.page,
|
||||
page_size: 10,
|
||||
};
|
||||
} else {
|
||||
jsonData = {
|
||||
page: this.page,
|
||||
page_size: 10,
|
||||
};
|
||||
}
|
||||
|
||||
this.api(jsonData).then((rep) => {
|
||||
var result = rep.data;
|
||||
this.loading = false;
|
||||
if (result.code == 200) {
|
||||
this.list = this.list.concat(result.data.list);
|
||||
if (result.data.list.length < 10) {
|
||||
this.finished = true;
|
||||
}
|
||||
if (this.type == "homeFollow" && this.list.length > 0) {
|
||||
this.$emit("getMyFollow", true);
|
||||
}
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
transforPages(arr, num) {
|
||||
const pages = [];
|
||||
arr.forEach((item, index) => {
|
||||
const page = Math.floor(index / num);
|
||||
if (!pages[page]) {
|
||||
pages[page] = [];
|
||||
}
|
||||
pages[page].push(item);
|
||||
});
|
||||
return pages;
|
||||
},
|
||||
handleCancelCollect(index, gandanhome_id) {
|
||||
this.$api
|
||||
.cancelCollect({
|
||||
gandanhome_id: gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[index], "is_collect", 0);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "已取消收藏",
|
||||
});
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggleCollect(iscollect, index, gandanhome_id) {
|
||||
iscollect == 0
|
||||
? this.handleCollect(index, gandanhome_id)
|
||||
: this.handleCancelCollect(index, gandanhome_id);
|
||||
},
|
||||
handleCollect(index, gandanhome_id) {
|
||||
this.$api
|
||||
.collect({
|
||||
gandanhome_id: gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[index], "is_collect", 1);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "收藏成功",
|
||||
});
|
||||
this.handleCompleteTask('task_add_collect')
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
toggleLike(isLike, index, gandanhome_id, likeNum) {
|
||||
isLike == 0
|
||||
? this.handleLike(gandanhome_id, index, likeNum)
|
||||
: this.handleCancelLike(gandanhome_id, index, likeNum);
|
||||
},
|
||||
handleCancelLike(gandanhome_id, index, likeNum) {
|
||||
this.$api
|
||||
.cancelLike({
|
||||
gandanhome_id: gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[index], "isLike", 0);
|
||||
this.$set(this.list[index], "likeNum", likeNum - 1);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "已取消点赞",
|
||||
});
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleLike(gandanhome_id, index, likeNum) {
|
||||
this.$api
|
||||
.like({
|
||||
gandanhome_id: gandanhome_id,
|
||||
})
|
||||
.then((rep) => {
|
||||
let result = rep.data;
|
||||
if (result.code == 200) {
|
||||
this.$set(this.list[index], "isLike", 1);
|
||||
this.$set(this.list[index], "likeNum", likeNum + 1);
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: "点赞成功",
|
||||
});
|
||||
this.handleCompleteTask('task_add_collect')
|
||||
} else {
|
||||
this.$toast({
|
||||
duration: 1000,
|
||||
message: rep.data.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.info .time {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.swiperbox {
|
||||
margin-top: 10px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.swiperbox .van-swipe {
|
||||
width: 100%;
|
||||
}
|
||||
.wraper >>> .van-swipe__indicator {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
opacity: 1;
|
||||
background-color: #fff;
|
||||
}
|
||||
.swiperbox>>> .van-swipe-item{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.swiperImg {
|
||||
margin:0 auto;
|
||||
width:auto;
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
height:142px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.swipebg{
|
||||
top:0;
|
||||
height:142px;
|
||||
position:absolute;
|
||||
width: 100%;
|
||||
opacity: 0.5;
|
||||
object-fit: contain;
|
||||
}
|
||||
.swipebg .swiperImg{
|
||||
width:100%;
|
||||
height:auto;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.settop {
|
||||
width: 35px;
|
||||
height: 15px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 15px;
|
||||
margin-left: 5px;
|
||||
background: linear-gradient(318deg, #3cc7c0 0%, #3cc7c0 0%, #6ef0e9 100%);
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
}
|
||||
.settop span {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
.ba {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: #f3f3f3;
|
||||
}
|
||||
.dealcell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 56px;
|
||||
font-size: 16px;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid #efefef;
|
||||
}
|
||||
.dealcell:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.more {
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
}
|
||||
.head[lazy="error"] {
|
||||
background: url("../assets/head.png") no-repeat center center;
|
||||
background-size: cover;
|
||||
}
|
||||
.imgbox {
|
||||
width: 100%;
|
||||
}
|
||||
.imgbox.tworow {
|
||||
width: 66.66%;
|
||||
}
|
||||
.imgbox .imgrow {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
/* justify-content: space-between; */
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.imgcell {
|
||||
flex: 1;
|
||||
max-width: 33.33%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.imgbox .imgcell:nth-child(2n) {
|
||||
text-align: center;
|
||||
}
|
||||
.imgbox .imgcell:nth-child(3n) {
|
||||
text-align: right;
|
||||
}
|
||||
.tulist {
|
||||
padding-top: 15px;
|
||||
height: calc(100vh - 180px);
|
||||
overflow-y: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.tool {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.address {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
.zan_comment {
|
||||
min-width: 75px;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.zan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.collectbox {
|
||||
margin: 0 20px;
|
||||
}
|
||||
.zan img,
|
||||
.comment img,
|
||||
.collectbox img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.comment {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.msgcell {
|
||||
background: #fff;
|
||||
padding: 8px 15px;
|
||||
border-bottom: 5px solid #f4f4f4;
|
||||
}
|
||||
|
||||
.namebox {
|
||||
width:100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.namebox .info {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
justify-content: space-between;
|
||||
margin-right: 10px;
|
||||
margin-left: 6px;
|
||||
flex-direction: column;
|
||||
}
|
||||
.namebox .left {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
}
|
||||
.msgcell .leftcon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.msgcell .avastar {
|
||||
width: 43px;
|
||||
height: 43px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.name_level {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.name_level .name {
|
||||
white-space: nowrap;
|
||||
font-size: 18px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.level {
|
||||
margin-left: 5px;
|
||||
margin-right: 4px;
|
||||
height: 15px;
|
||||
}
|
||||
.level:first-child {
|
||||
margin-left: 4px;
|
||||
}
|
||||
.listbox {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.listbox .cell {
|
||||
margin: 0 15px;
|
||||
padding: 13px 10px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #efefef;
|
||||
}
|
||||
.listbox .cell .head {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.fllow {
|
||||
width: 68px;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #ffffff;
|
||||
border-radius: 25px;
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
.listbox .cell .name {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.listbox .cell:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.listbox .cell .left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.msglist .title {
|
||||
line-height: 23px;
|
||||
margin-top: 12px;
|
||||
font-size: 17px;
|
||||
color: #000000;
|
||||
}
|
||||
.msglist .msgdetail {
|
||||
margin-top: 4px;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: #666666;
|
||||
}
|
||||
.msglist .msgdetail span {
|
||||
color: #3cc7c0;
|
||||
}
|
||||
.msglist {
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
68
src/components/totop.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<!-- <div> -->
|
||||
<div class="goTop" v-show="goTopShow" @click="goTop">
|
||||
<img src="../assets/top.png" alt="">
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, watch,onMounted,onUnmounted } from "vue"
|
||||
const scrollTop = ref(0);
|
||||
const goTopShow = ref(false);
|
||||
watch(scrollTop, () => {
|
||||
if (scrollTop.value > 250) {
|
||||
goTopShow.value = true;
|
||||
} else {
|
||||
goTopShow.value = false;
|
||||
}
|
||||
})
|
||||
const handleScroll = () => {
|
||||
|
||||
scrollTop.value = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
|
||||
if (scrollTop.value > 250) {
|
||||
goTopShow.value = true;
|
||||
}else{
|
||||
goTopShow.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const goTop = () => {
|
||||
let timer = setInterval(() => {
|
||||
let ispeed = Math.floor(-scrollTop.value / 5)
|
||||
document.body.scrollTop = scrollTop.value + ispeed
|
||||
document.documentElement.scrollTop = scrollTop.value + ispeed
|
||||
if (scrollTop.value === 0) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 20)
|
||||
|
||||
|
||||
|
||||
};
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.goTop {
|
||||
position: fixed;
|
||||
width: 69px;
|
||||
height: 30px;
|
||||
right:0px;
|
||||
bottom:135px;
|
||||
cursor: pointer;
|
||||
z-index:999;
|
||||
overflow: hidden;
|
||||
border-radius: 15px 0 0 15px;
|
||||
box-shadow: 0 0 6px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.goTop img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
33
src/main.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { createApp } from 'vue'
|
||||
import 'reset-css'
|
||||
import 'vant/lib/index.css';
|
||||
import App from './App.vue'
|
||||
import router from "@/router/index.js"
|
||||
import Loading from "@/components/loading/index"
|
||||
import { Image as VanImage } from 'vant';
|
||||
import {Toast,ImagePreview,Lazyload,Overlay, List,Tab, Tabs,PullRefresh,CountDown,Checkbox, CheckboxGroup, RadioGroup, Radio,Field } from 'vant';
|
||||
import VConsole from 'vconsole';
|
||||
if(import.meta.env.MODE!=='production') {
|
||||
const vConsole = new VConsole();
|
||||
};
|
||||
const app = createApp(App);
|
||||
app.config.compilerOptions.isCustomElement = (tag) => { return tag.startsWith('wx-open-launch-weapp') }
|
||||
app.use(router);
|
||||
app.use(VanImage);
|
||||
app.use(List);
|
||||
app.use(Tab);
|
||||
app.use(Tabs);
|
||||
app.use(PullRefresh);
|
||||
app.use(CountDown);
|
||||
app.use(Checkbox);
|
||||
app.use(CheckboxGroup)
|
||||
app.use(Radio);
|
||||
app.use(RadioGroup);
|
||||
app.use(Field);
|
||||
app.use(Overlay);
|
||||
app.use(Toast);
|
||||
app.use(Lazyload );
|
||||
app.use(ImagePreview)
|
||||
app.use(Loading)
|
||||
app.mount('#app')
|
||||
|
||||
149
src/router/index.js
Normal file
@ -0,0 +1,149 @@
|
||||
import {
|
||||
createWebHashHistory,
|
||||
createRouter,
|
||||
createWebHistory
|
||||
} from 'vue-router';
|
||||
import api from '../api/user.js';
|
||||
import cookie from '@/utils/cookie.js';
|
||||
import host from "../utils/host.js"
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
component: () => import('@/views/home.vue')
|
||||
},
|
||||
{
|
||||
path: '/caseList',
|
||||
name: 'caseList',
|
||||
component: () => import('@/views/caseList.vue')
|
||||
},
|
||||
{
|
||||
path: '/caseIntro',
|
||||
name: 'caseIntro',
|
||||
component: () => import('@/views/caseIntro.vue')
|
||||
},
|
||||
{
|
||||
path: '/caseDetail',
|
||||
name: 'caseDetail',
|
||||
component: () => import('@/views/caseDetail.vue')
|
||||
},
|
||||
{
|
||||
path: '/comment',
|
||||
name: 'comment',
|
||||
component: () => import('@/views/comment.vue')
|
||||
},
|
||||
{
|
||||
path: '/result',
|
||||
name: 'result',
|
||||
component: () => import('@/views/result.vue')
|
||||
},
|
||||
];
|
||||
const router = createRouter({
|
||||
// createWebHashHistory URL 带井号
|
||||
// createWebHistory URL 去井号
|
||||
history:createWebHistory('web'),
|
||||
routes: routes,
|
||||
});
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
if(to.path!=='/caseIntro' || to.path!=='/result'){
|
||||
document.title = '互动病例';
|
||||
}
|
||||
let source=to.query.source
|
||||
// 权限验证逻辑
|
||||
if (source == 3) {
|
||||
if(to.path!=='/result'){
|
||||
localStorage.setItem('token_other','')
|
||||
}
|
||||
let token=localStorage.getItem('token_other');
|
||||
if(!token){
|
||||
const {data,code}=await api.login({
|
||||
source:3,
|
||||
platform_key:to.query.platform_key,
|
||||
user_iden:to.query.user_iden,
|
||||
mobile_encryption:to.query.mobile_encryption,
|
||||
doctor_name:to.query.doctor_name,
|
||||
hospital_name:to.query.hospital_name,
|
||||
department_name:to.query.department_name,
|
||||
address:to.query.address,
|
||||
title:to.query.title,
|
||||
share_user_id:to.query.share_user_id,
|
||||
is_white:to.query.is_white,
|
||||
project_id:to.query.project_id
|
||||
})
|
||||
if(code==200){
|
||||
localStorage.setItem('token_other',data.token);
|
||||
localStorage.setItem('userInfo',JSON.stringify(data));
|
||||
localStorage.setItem('source',3);
|
||||
next();
|
||||
}
|
||||
}else{
|
||||
next();
|
||||
}
|
||||
|
||||
} else {
|
||||
//localStorage.setItem('token_gandan','eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTg5NDI3NjIyOTg5NzM5MjEyOCIsInBsYXRmb3JtX2lkIjoiMSIsImV4cCI6MTc0MTMyNzk2OSwibmJmIjoxNzQxMDY4NzY5LCJpYXQiOjE3NDEwNjg3Njl9.xItE3sfBb438X5vZUOWptzahKKUutu0QPFrXo0pi53Y');
|
||||
let token='';
|
||||
let token_other=localStorage.getItem('token_other');
|
||||
let token_gandan=localStorage.getItem('token_gandan');
|
||||
if(source==3){
|
||||
if(token_other){
|
||||
token=token_other;
|
||||
}
|
||||
}else{
|
||||
if(token_gandan){
|
||||
token=token_gandan;
|
||||
}
|
||||
}
|
||||
if(!token){
|
||||
let unionid='';
|
||||
let userInfo=cookie.readCookie('wechat_user_info');
|
||||
let videoToken=cookie.readCookie('video_token');
|
||||
if(userInfo){
|
||||
let json=JSON.parse(userInfo);
|
||||
unionid=json.unionid;
|
||||
const {data,code}=await api.login({
|
||||
source:2,
|
||||
platform_key:123456,
|
||||
unionid:unionid?unionid:'',
|
||||
user_iden:to.query.uuid?to.query.uuid:'',
|
||||
})
|
||||
if(code==200){
|
||||
localStorage.setItem('token_gandan',data.token);
|
||||
localStorage.setItem('userInfo',JSON.stringify(data));
|
||||
localStorage.setItem('source','');
|
||||
next();
|
||||
}
|
||||
}else if(videoToken){
|
||||
const {data,code}=await api.login({
|
||||
source:2,
|
||||
platform_key:123456,
|
||||
unionid:unionid?unionid:'',
|
||||
user_iden:to.query.uuid?to.query.uuid:'',
|
||||
token:videoToken
|
||||
})
|
||||
if(code==200){
|
||||
localStorage.setItem('token_gandan',data.token);
|
||||
localStorage.setItem('userInfo',JSON.stringify(data));
|
||||
localStorage.setItem('source','');
|
||||
next();
|
||||
}
|
||||
}else{
|
||||
let url='https://dev-wx.igandan.com';
|
||||
if(host.indexOf('//dev-caseplatform.igandan.com')==-1){
|
||||
url='https://wx.igandan.com'
|
||||
}
|
||||
window.location.href = url+"/hcp/Signup2020online_tologin?back_url="+host+"/web/home"
|
||||
}
|
||||
}else{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
export default router;
|
||||
5
src/style.css
Normal file
@ -0,0 +1,5 @@
|
||||
body{
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
|
||||
249
src/utils/HCPUtils.js
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* HCP 整合js
|
||||
*/
|
||||
//'use strict';
|
||||
|
||||
import $ from 'jquery';
|
||||
import {Base64} from 'js-base64';
|
||||
var localStorage_name = "watchlive_current_user"
|
||||
localStorage.setItem("watch_live_localStorage_name",localStorage_name);
|
||||
window.finsihed=null;
|
||||
var current_user = {
|
||||
id:"",
|
||||
name:'',
|
||||
avatar:''
|
||||
};
|
||||
function getUrlParam(url, paramName) {
|
||||
const reg = new RegExp('(^|&)' + paramName + '=([^&]*)(&|$)', 'i');
|
||||
const result = url.slice(url.indexOf('?') + 1).match(reg);
|
||||
if (result !== null) {
|
||||
return decodeURIComponent(result[2]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function init_current_user(){
|
||||
console.log("init_current_user")
|
||||
current_user = JSON.parse(localStorage.getItem(localStorage_name));
|
||||
if(current_user == undefined || current_user == null){
|
||||
current_user =
|
||||
{
|
||||
id: timestamp(),
|
||||
name: Base64.encode("游客"+timestamp()),
|
||||
avatar: "https://doc.igandan.com/app/html/img/2016/20160714132557.png"
|
||||
}
|
||||
}
|
||||
return current_user;
|
||||
}
|
||||
var timestamp = function(){
|
||||
return new Date().getTime();
|
||||
}
|
||||
const HCP = {
|
||||
options: {
|
||||
privilege_async: false, //获取权限时ajax同步异步 (ajax 默认是true:异步,false:同步。)
|
||||
user_info_async: false, //获取用户信息时ajax同步异步 (ajax 默认是true:异步,false:同步。)
|
||||
add_sources_async: true, //获取权限时ajax同步异步 (ajax 默认是true:异步,false:同步。)
|
||||
},
|
||||
current_user: init_current_user(),//当前用户信息
|
||||
privilege: {},//权限信息
|
||||
//获取属性值
|
||||
getOption: function (name){
|
||||
return HCP.options[name]
|
||||
},
|
||||
//设置属性值
|
||||
setOption: function(name,value){
|
||||
return HCP.options[name] = value
|
||||
},
|
||||
|
||||
//检查HCP权限
|
||||
getHCPPrivilege: async function(gdxz_unionid,from,project_id){
|
||||
let baseUrl = '';
|
||||
var path=location.href;
|
||||
if (path.indexOf("//wx.igandan.com") > 1 || path.indexOf("oss")>1) {
|
||||
baseUrl='https://wx.igandan.com'
|
||||
|
||||
} else {
|
||||
baseUrl='https://dev-wx.igandan.com'
|
||||
}
|
||||
await $.ajax({
|
||||
url: baseUrl+"/hcp/getHCPPrivilege",
|
||||
//url:'https://www.fastmock.site/mock/ebb1956b65d6078940cacb295a06be27/mock/mock',
|
||||
async: HCP.options.privilege_async,
|
||||
data: {"unionid":gdxz_unionid, "from": from, "project_id":project_id},
|
||||
success:function(res){// 获取用户信息,后端可首先通过cookie,session等判断,没有信息则通过code获取
|
||||
//alert(JSON.stringify(res))
|
||||
console.log(res);
|
||||
if (res.code == 60001) {
|
||||
window.finsihed=true;
|
||||
//alert("getHCPPrivilege");
|
||||
console.log("授权成功")
|
||||
//console.log(HCP.privilege.HCP_INFO);
|
||||
localStorage.setItem("userName", Base64.decode(res.HCP_INFO.nickname));
|
||||
localStorage.setItem("uuid", res.HCP_INFO.user_uuid);
|
||||
localStorage.setItem("avatar", res.HCP_INFO.avatar);
|
||||
} else if (res.code == 60002) {
|
||||
Dialog.alert({
|
||||
title: '提示信息',
|
||||
message: '您暂时没有权限,无法浏览,请关闭页面',
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
} else {
|
||||
//alert("222");
|
||||
//直接走登录页面
|
||||
HCP.gologin();
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
//添加HCP 访问记录
|
||||
addSources: function(openid,sourcesId,sourcesTitle, sourcesType,userid,userType){
|
||||
$.ajax({
|
||||
url: "/hcp/addSources",
|
||||
async: HCP.options.add_sources_async,
|
||||
data: {
|
||||
openid:openid,
|
||||
sourcesId:sourcesId,
|
||||
sourcesTitle:sourcesTitle,
|
||||
sourcesType:sourcesType,
|
||||
userid:userid,
|
||||
userType:userType
|
||||
},
|
||||
success:function(res){
|
||||
//...
|
||||
}
|
||||
})
|
||||
},
|
||||
//转到login页面
|
||||
gologin: function (){
|
||||
let baseUrl = '';
|
||||
var path=location.href;
|
||||
if (path.indexOf("//wx.igandan.com") > 1 || path.indexOf("oss")>1) {
|
||||
baseUrl='https://wx.igandan.com'
|
||||
} else {
|
||||
baseUrl='https://dev-wx.igandan.com'
|
||||
}
|
||||
var path=location.href.split('#')[0];
|
||||
window.location.href =baseUrl+"/hcp/Signup2020online_tologin?back_url="+HCP.htmlDecodeByRegExp(path);
|
||||
},
|
||||
//反转义
|
||||
htmlDecodeByRegExp: function (str){
|
||||
var s = "";
|
||||
if(str.length == 0) return "";
|
||||
s = str.replace(/&/g,"&");
|
||||
s = s.replace(/</g,"<");
|
||||
s = s.replace(/>/g,">");
|
||||
s = s.replace(/ /g," ");
|
||||
s = s.replace(/'/g,"\'");
|
||||
s = s.replace(/"/g,"\"");
|
||||
return s;
|
||||
} ,
|
||||
//判断字符串是否为空
|
||||
isNull: function (str) {
|
||||
if (typeof (str) == "undefined" || str == "undefined" || str == null || str.replace(" ") === "")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
//获取cookie
|
||||
getCookie: function (name){
|
||||
var arr;
|
||||
var reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
|
||||
if (arr = document.cookie.match(reg))
|
||||
return unescape(arr[2]);
|
||||
else
|
||||
return null;
|
||||
// var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
|
||||
// if(arr=document.cookie.match(reg))
|
||||
// return unescape(arr[2]);
|
||||
// else
|
||||
// return null;
|
||||
},
|
||||
//设置cookie
|
||||
setCookie: function (cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||
var expires = "expires="+ d.toUTCString();
|
||||
document.cookie = cname + "=" + cvalue + ";" + expires;
|
||||
|
||||
},
|
||||
//是否为微信
|
||||
is_weixin: function (){
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if(ua.match(/MicroMessenger/i)=="micromessenger") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
//获得时间戳
|
||||
timestamp: function(){
|
||||
return new Date().getTime();
|
||||
},
|
||||
//获取微信用户信息
|
||||
getUserInfo: function (){
|
||||
let code =getUrlParam("code") ;// 截取url上的code ,可能没有,则返回''空字符串!HCP.getCookie("gdxz_unionid")?'':
|
||||
var path=location.href; //.split('#')[0];
|
||||
var url="";
|
||||
var appid="";
|
||||
if (path.indexOf("//wx.igandan.com") > 1) {
|
||||
url="https://wx.igandan.com/";
|
||||
appid="wxa4132ef4701ac5e4";
|
||||
|
||||
} else {
|
||||
url="https://dev-wx.igandan.com/";
|
||||
appid="wx68affaa9d23528f8";
|
||||
}
|
||||
// if(path.indexOf(".igandan.org")>1){
|
||||
// url="https://twx.igandan.org/";
|
||||
// appid="wx68affaa9d23528f8";
|
||||
// }else{
|
||||
// url="https://wx.igandan.com/";
|
||||
// appid="wxa4132ef4701ac5e4";
|
||||
// }
|
||||
const ishttps = 'https:' == document.location.protocol ? true : false;
|
||||
if(!ishttps){
|
||||
url = url.toString().replace("https","http")
|
||||
};
|
||||
$.ajax({
|
||||
url: url+"AuthorizeURL/getUserInfo",
|
||||
data: {appid:appid, code: code, scope: "snsapi_userinfo"},
|
||||
async: HCP.options.user_info_async,
|
||||
success:function(res){// 获取用户信息,后端可首先通过cookie,session等判断,没有信息则通过code获取
|
||||
if(res.code == 200 ){
|
||||
var user_info = JSON.parse(res.user_info.json)
|
||||
current_user = {
|
||||
id: user_info.openid,
|
||||
name: Base64.encode(user_info.nickname),
|
||||
avatar: user_info.headimgurl,
|
||||
unionid: user_info.unionid,
|
||||
};
|
||||
HCP.current_user = current_user;
|
||||
HCP.setCookie("gdxz_unionid", user_info.unionid, 1);
|
||||
localStorage.setItem(localStorage_name,JSON.stringify(current_user));
|
||||
//alert("即将重新加载")
|
||||
window.location.reload();
|
||||
//HCP.getHCPPrivilege(user_info.unionid, "wechat", "")
|
||||
// var currentHref=sessionStorage.getItem("currentHref");
|
||||
// if(currentHref){
|
||||
// window.location.href=currentHref;
|
||||
// }
|
||||
}else if(res.code == 202){
|
||||
// 这个redirectUrl用 当前页路径或者tof.fullPath(将要进入的路径)
|
||||
//var myurl="https://" + window.location.host +"/excellencourse/index.htm?"+window.location.href.split("?")[1];
|
||||
var redirectUrl =window.location.href;
|
||||
//sessionStorage.setItem("currentHref",redirectUrl)
|
||||
redirectUrl = encodeURIComponent(redirectUrl);
|
||||
var oauth2_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
|
||||
var appid = res.appid;
|
||||
window.location.href = oauth2_url.replace("APPID",appid).replace("REDIRECT_URI",redirectUrl);
|
||||
//window.location.reload();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default HCP
|
||||
|
||||
243
src/utils/axios.js
Normal file
@ -0,0 +1,243 @@
|
||||
import axios from "axios";
|
||||
import { showToast,showDialog } from 'vant';
|
||||
import host from "./host"
|
||||
import wx from 'jweixin-1.6.0'
|
||||
|
||||
// 1. 创建axios实例
|
||||
const instance = axios.create({
|
||||
// 接口
|
||||
baseURL: import.meta.env.VITE_BASE_URL,
|
||||
// 超时时间
|
||||
timeout: 100000,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
});
|
||||
// 2.请求拦截
|
||||
instance.interceptors.request.use(
|
||||
config => {
|
||||
let token='';
|
||||
let token_gandan = localStorage.getItem('token_gandan');
|
||||
let token_other = localStorage.getItem('token_other');
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
let source=params.get('source');
|
||||
if(source==3){
|
||||
if(token_other){
|
||||
token=token_other;
|
||||
}
|
||||
}else{
|
||||
if(token_gandan){
|
||||
token=token_gandan;
|
||||
}
|
||||
}
|
||||
if (token) {
|
||||
config.headers['Authorization'] ='Bearer '+token
|
||||
}
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
// 请求发生错误,抛出异常
|
||||
Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// 3.响应拦截
|
||||
instance.interceptors.response.use(
|
||||
res => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
let source=params.get('source');
|
||||
if (res.data && res.data.code === 200 ) {
|
||||
//let status=res.data.code;
|
||||
return res.data;
|
||||
}else{
|
||||
let status=res.data.code;
|
||||
switch (status) {
|
||||
case 201:
|
||||
localStorage.clear();
|
||||
showToast("该账户已被禁用");
|
||||
break;
|
||||
case -1:
|
||||
if(res.data.data.source==3){
|
||||
showDialog({
|
||||
width: '80%',
|
||||
title: '提示',
|
||||
message: '跳转失败,请返回重试',
|
||||
}).then(() => {
|
||||
wx.miniProgram.navigateBack({
|
||||
fail:function(res) {
|
||||
wx.miniProgram.switchTab({
|
||||
url: '/pages/media_home/index'
|
||||
})
|
||||
}
|
||||
});
|
||||
// wx.miniProgram.switchTab({
|
||||
// url: '/pages/media_home/index',
|
||||
// success(res) {
|
||||
// consoe.log('跳转成功');
|
||||
// },
|
||||
// fail(res) {
|
||||
// consoe.log('跳转失败');
|
||||
// }
|
||||
// });
|
||||
});
|
||||
}else{
|
||||
showToast(res.data.message);
|
||||
}
|
||||
return res.data;
|
||||
break;
|
||||
case -2:
|
||||
localStorage.clear();
|
||||
//showToast('该账户未注册');
|
||||
let url='https://dev-wx.igandan.com';
|
||||
if(host.indexOf('//dev-caseplatform.igandan.com')==-1){
|
||||
url='https://wx.igandan.com'
|
||||
}
|
||||
window.location.href = url+"/hcp/Signup2020online_tologin?back_url="+host+"/web/home"
|
||||
break;
|
||||
case 400:
|
||||
showToast("请求错误");
|
||||
break;
|
||||
case 401:
|
||||
showToast("未授权,请重新登录");
|
||||
if(source==3){
|
||||
localStorage.clear();
|
||||
wx.miniProgram.navigateBack({
|
||||
fail:function(res) {
|
||||
wx.miniProgram.switchTab({
|
||||
url: '/pages/media_home/index'
|
||||
})
|
||||
}
|
||||
});
|
||||
// wx.miniProgram.switchTab({
|
||||
// url: '/pages/media_home/index',
|
||||
// success(res) {
|
||||
// consoe.log('跳转成功');
|
||||
// },
|
||||
// fail(res) {
|
||||
// consoe.log('跳转失败');
|
||||
// }
|
||||
// });
|
||||
}else{
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
showToast("拒绝访问");
|
||||
break;
|
||||
case 404:
|
||||
showToast("请求错误,未找到相应的资源");
|
||||
break;
|
||||
case 405:
|
||||
showToast("未授权,请重新登录");
|
||||
if(source==3){
|
||||
localStorage.clear();
|
||||
wx.miniProgram.navigateBack({
|
||||
fail:function(res) {
|
||||
wx.miniProgram.switchTab({
|
||||
url: '/pages/media_home/index'
|
||||
})
|
||||
}
|
||||
});
|
||||
// wx.miniProgram.switchTab({
|
||||
// url: '/pages/media_home/index',
|
||||
// success(res) {
|
||||
// consoe.log('跳转成功');
|
||||
// },
|
||||
// fail(res) {
|
||||
// consoe.log('跳转失败');
|
||||
// }
|
||||
// });
|
||||
}else{
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
break;
|
||||
case 408:
|
||||
showToast("请求超时");
|
||||
break;
|
||||
case 500:
|
||||
showToast("服务器内部错误");
|
||||
break;
|
||||
case 501:
|
||||
showToast("网络未实现");
|
||||
break;
|
||||
case 502:
|
||||
showToast("网络错误");
|
||||
break;
|
||||
case 503:
|
||||
showToast("服务不可用");
|
||||
break;
|
||||
case 504:
|
||||
showToast("网络超时");
|
||||
break;
|
||||
case 505:
|
||||
showToast("HTTP版本不支持该请求");
|
||||
break;
|
||||
default:
|
||||
return res.data;
|
||||
//ElMessage.error("请求失败");
|
||||
}
|
||||
//return res;
|
||||
}
|
||||
|
||||
},
|
||||
error => {
|
||||
if (error && error.response) {
|
||||
const status = error.response.status
|
||||
switch (status) {
|
||||
case 201:
|
||||
localStorage.clear()
|
||||
showToast("该账户已被禁用");
|
||||
break;
|
||||
case 400:
|
||||
showToast("请求错误");
|
||||
break;
|
||||
case 401:
|
||||
localStorage.clear()
|
||||
window.location.reload();
|
||||
showToast("未授权,请重新登录");
|
||||
break;
|
||||
case 403:
|
||||
showToast("拒绝访问");
|
||||
break;
|
||||
case 404:
|
||||
showToast("请求错误,未找到相应的资源");
|
||||
break;
|
||||
case 408:
|
||||
showToast("请求超时");
|
||||
break;
|
||||
case 500:
|
||||
showToast("服务器内部错误");
|
||||
break;
|
||||
case 501:
|
||||
showToast("网络未实现");
|
||||
break;
|
||||
case 502:
|
||||
showToast("网络错误");
|
||||
break;
|
||||
case 503:
|
||||
showToast("服务不可用");
|
||||
break;
|
||||
case 504:
|
||||
showToast("网络超时");
|
||||
break;
|
||||
case 505:
|
||||
showToast("HTTP版本不支持该请求");
|
||||
break;
|
||||
default:
|
||||
showToast("请求失败");
|
||||
}
|
||||
} else {
|
||||
if (JSON.stringify(error).includes("timeout")) {
|
||||
showToast("服务器响应超时,请刷新页面");
|
||||
}
|
||||
showToast("连接服务器失败");
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 4.导出 axios 实例
|
||||
export default instance;
|
||||
|
||||
33
src/utils/cookie.js
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
const cookie = {
|
||||
//写cookies
|
||||
setCookie: function(name, value) {
|
||||
//let days = 0.5;
|
||||
let exp = new Date();
|
||||
exp.setTime(exp.getTime() + 15*60*1000)
|
||||
|
||||
// exp.setTime(exp.getTime() + days*24*60*60*1000)
|
||||
document.cookie = name + '=' + escape (value) + ';expires=' + exp.toGMTString()
|
||||
},
|
||||
//读取cookies
|
||||
readCookie: function (name) {
|
||||
let arr = null
|
||||
let reg = new RegExp('(^| )'+name+'=([^;]*)(;|$)')
|
||||
if (document.cookie && (arr = document.cookie.match(reg))) {
|
||||
return unescape(arr[2])
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
//删除cookies
|
||||
delCookie: function (name) {
|
||||
let cval = this.readCookie(name);
|
||||
var domain = '.igandan.com';
|
||||
if (cval!=null) {
|
||||
document.cookie = name + '=;expires=' + (new Date(0)).toGMTString()+";path=/;domain="+domain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default cookie
|
||||
|
||||
60
src/utils/getUrlParam.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* @Author: Administrator
|
||||
* @Date: 2017-10-27 11:30:07
|
||||
* @Last Modified by: Administrator
|
||||
* @Last Modified time: 2017-10-27 11:30:36
|
||||
*/
|
||||
var UrlParm = function() { // url参数
|
||||
var data, index;
|
||||
(function init() {
|
||||
data = [];
|
||||
index = {};
|
||||
var u = window.location.search.substr(1);
|
||||
if (u != '') {
|
||||
var parms = decodeURIComponent(u).split('&');
|
||||
for (var i = 0, len = parms.length; i < len; i++) {
|
||||
if (parms[i] != '') {
|
||||
var p = parms[i].split("=");
|
||||
if (p.length == 1 || (p.length == 2 && p[1] == '')) {// p | p=
|
||||
data.push(['']);
|
||||
index[p[0]] = data.length - 1;
|
||||
} else if (typeof(p[0]) == 'undefined' || p[0] == '') { // =c | =
|
||||
data[0] = [p[1]];
|
||||
} else if (typeof(index[p[0]]) == 'undefined') { // c=aaa
|
||||
data.push([p[1]]);
|
||||
index[p[0]] = data.length - 1;
|
||||
} else {// c=aaa
|
||||
data[index[p[0]]].push(p[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
return {
|
||||
// 获得参数,类似request.getParameter()
|
||||
parm : function(o) { // o: 参数名或者参数次序
|
||||
try {
|
||||
return (typeof(o) == 'number' ? data[o][0] : data[index[o]][0]);
|
||||
} catch (e) {
|
||||
}
|
||||
},
|
||||
//获得参数组, 类似request.getParameterValues()
|
||||
parmValues : function(o) { // o: 参数名或者参数次序
|
||||
try {
|
||||
return (typeof(o) == 'number' ? data[o] : data[index[o]]);
|
||||
} catch (e) {}
|
||||
},
|
||||
//是否含有parmName参数
|
||||
hasParm : function(parmName) {
|
||||
return typeof(parmName) == 'string' ? typeof(index[parmName]) != 'undefined' : false;
|
||||
},
|
||||
// 获得参数Map ,类似request.getParameterMap()
|
||||
parmMap : function() {
|
||||
var map = {};
|
||||
try {
|
||||
for (var p in index) { map[p] = data[index[p]]; }
|
||||
} catch (e) {}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}();
|
||||
35
src/utils/hcpRight.js
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
import HCP from "./HCPUtils.js"
|
||||
import host from "./host.js"
|
||||
var gdxz_unionid = HCP.getCookie("gdxz_unionid");
|
||||
var from;
|
||||
|
||||
const hcpRight = async function () {
|
||||
if (HCP.is_weixin()) {
|
||||
from = "wechat";
|
||||
if (HCP.isNull(gdxz_unionid)) {
|
||||
//await HCP.getUserInfo();
|
||||
window.location.href = "https://dev-wx.igandan.com/hcp/Signup2020online_tologin?back_url=https://dev-caseplatform.igandan.com/web/home"
|
||||
// var redirectUrl = encodeURIComponent(window.location.href);
|
||||
// let url='https://dev-wx.igandan.com';
|
||||
// if(host.indexOf('//dev-caseplatform.igandan.com')==-1){
|
||||
// url='https://wx.igandan.com'
|
||||
// }
|
||||
// window.location.href = url+"/AuthorizeURL/grant?back_url=" + redirectUrl;
|
||||
|
||||
}else{
|
||||
await HCP.getHCPPrivilege(gdxz_unionid, from, "")
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
gdxz_unionid = "";
|
||||
from = "gdxzAPP";
|
||||
HCP.getHCPPrivilege(gdxz_unionid, from, "");
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default hcpRight;
|
||||
9
src/utils/host.js
Normal file
@ -0,0 +1,9 @@
|
||||
let host='';
|
||||
let path=window.location.href;
|
||||
if (path.indexOf("//prod-caseplatform.igandan.com") > 1 ) {
|
||||
host = "https://prod-caseplatform.igandan.com";
|
||||
} else {
|
||||
host = "https://dev-caseplatform.igandan.com";
|
||||
|
||||
}
|
||||
export default host;
|
||||
53
src/utils/http.js
Normal file
@ -0,0 +1,53 @@
|
||||
import instance from "./axios"
|
||||
|
||||
const post = (url, data,header='application/x-www-form-urlencoded') => {
|
||||
return new Promise((resolve, reject) => {
|
||||
instance.post(url, data,{
|
||||
headers: {
|
||||
"Content-Type": header,
|
||||
},
|
||||
}).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
const get = (url, data={}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
instance.get(url, { params: data }).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
const put = (url, data,header='application/x-www-form-urlencoded') => {
|
||||
return new Promise((resolve, reject) => {
|
||||
instance.put(url, data,{
|
||||
headers: {
|
||||
"Content-Type": header,
|
||||
},
|
||||
}).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const del = (url, data,header='application/x-www-form-urlencoded') => {
|
||||
return new Promise((resolve, reject) => {
|
||||
instance.delete(url,data, {headers: {
|
||||
"Content-Type": header,
|
||||
}}).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
post, get, put, del
|
||||
}
|
||||
45
src/utils/openTag.js
Normal file
@ -0,0 +1,45 @@
|
||||
import wx from 'weixin-js-sdk'
|
||||
import axios from 'axios'
|
||||
function openTag(){
|
||||
var path = location.href.split('#')[0];
|
||||
var url = "";
|
||||
var appid = "";
|
||||
if (path.indexOf("//dev") > 1) {
|
||||
url = "https://dev-app.igandan.com/app/manager/getSignature4bing";
|
||||
appid = "wx68affaa9d23528f8";
|
||||
} else {
|
||||
url = "https://app.igandan.com/app/manager/getSignature4bing";
|
||||
appid = "wxa4132ef4701ac5e4";
|
||||
}
|
||||
|
||||
axios.get(url, {
|
||||
params: {
|
||||
path: encodeURIComponent(window.location.href.split('#')[0]),
|
||||
appid: appid
|
||||
}
|
||||
}).then(json => {
|
||||
wx.config({
|
||||
debug: false,
|
||||
appId: appid,
|
||||
timestamp: json.data.timestamp,
|
||||
nonceStr: json.data.nonceStr,
|
||||
signature: json.data.signature,
|
||||
jsApiList: ['wx-open-launch-weapp'],
|
||||
openTagList: ['wx-open-launch-weapp']
|
||||
});
|
||||
}).catch((e) => {
|
||||
console.log('获取数据失败');
|
||||
});
|
||||
wx.checkJsApi({
|
||||
jsApiList: ['wx-open-launch-weapp'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
|
||||
success: function (res) {
|
||||
console.log(res)
|
||||
}
|
||||
});
|
||||
wx.ready(function () {
|
||||
console.log('准备好了~~~');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export default openTag;
|
||||
9
src/utils/version.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
let version='';
|
||||
//let appid = "wx68affaa9d23528f8";
|
||||
if (import.meta.env.MODE ==='production') {
|
||||
version = "release";
|
||||
} else {
|
||||
version = "trial";
|
||||
}
|
||||
export default version;
|
||||
94
src/utils/wxshare-1.6.0.js
Normal file
@ -0,0 +1,94 @@
|
||||
import wx from 'weixin-js-sdk'
|
||||
import axios from 'axios'
|
||||
let share = {
|
||||
title: "",
|
||||
desc: "",
|
||||
link: "",
|
||||
imgUrl: "",
|
||||
init: function () {
|
||||
var path = location.href.split('#')[0];
|
||||
var url = "";
|
||||
var appid = "";
|
||||
if (path.indexOf("//wx.igandan.com") > 1 || path.indexOf("oss")>1) {
|
||||
url = "https://app.igandan.com/app/manager/getSignature4bing";
|
||||
appid = "wxa4132ef4701ac5e4";
|
||||
|
||||
} else {
|
||||
url = "https://dev-app.igandan.com/app/manager/getSignature4bing";
|
||||
appid = "wx68affaa9d23528f8";
|
||||
}
|
||||
|
||||
axios.get(url, {
|
||||
params: {
|
||||
path: encodeURIComponent(window.location.href.split('#')[0]),
|
||||
appid: appid
|
||||
}
|
||||
}).then(json => {
|
||||
wx.config({
|
||||
debug: false,
|
||||
appId: appid,
|
||||
timestamp: json.data.timestamp,
|
||||
nonceStr: json.data.nonceStr,
|
||||
signature: json.data.signature,
|
||||
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage','chooseImage'],
|
||||
openTagList: ['wx-open-launch-app','chooseImage']
|
||||
});
|
||||
}).catch((e) => {
|
||||
console.log('获取数据失败');
|
||||
});
|
||||
wx.checkJsApi({
|
||||
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
|
||||
success: function (res) {
|
||||
console.log(res)
|
||||
}
|
||||
});
|
||||
wx.ready(function () {
|
||||
|
||||
|
||||
wx.updateAppMessageShareData({
|
||||
title: share.title,
|
||||
desc: share.desc,
|
||||
link: share.link,
|
||||
imgUrl: share.imgUrl,
|
||||
success: function () {}
|
||||
})
|
||||
wx.updateTimelineShareData({
|
||||
title: share.title,
|
||||
desc: share.desc,
|
||||
link: share.link,
|
||||
imgUrl: share.imgUrl,
|
||||
success: function () {}
|
||||
})
|
||||
wx.onMenuShareTimeline({
|
||||
title: share.title,
|
||||
desc: share.desc,
|
||||
link: share.link,
|
||||
imgUrl: share.imgUrl,
|
||||
success: function () {}
|
||||
})
|
||||
wx.onMenuShareAppMessage({
|
||||
title: share.title,
|
||||
desc: share.desc,
|
||||
link: share.link,
|
||||
imgUrl: share.imgUrl,
|
||||
success: function () {}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function WXSHARE(title, desc, link, imgUrl) {
|
||||
share.title = title;
|
||||
share.desc = desc;
|
||||
share.link = link;
|
||||
if (imgUrl == undefined || imgUrl == "") {
|
||||
imgUrl = "https://doc.igandan.com/app/html/img/2016/20160714132557.png";
|
||||
}
|
||||
share.imgUrl = imgUrl;
|
||||
share.init();
|
||||
};
|
||||
|
||||
|
||||
export {
|
||||
WXSHARE
|
||||
}
|
||||
422
src/views/caseDetail.vue
Normal file
@ -0,0 +1,422 @@
|
||||
<template>
|
||||
<div class="main" :id="'pagemain'+pageIndex" v-show="step == pageIndex" >
|
||||
<img src="../assets/bg.png" alt="" class="bg" />
|
||||
<div class="dealbox">
|
||||
<div class="prev" @click="switchPage(pageIndex - 1)">上一步</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="pagebox">
|
||||
<div class="page">
|
||||
<!-- <div class="card" v-html="pageItem.content"></div> -->
|
||||
<div
|
||||
class="card"
|
||||
v-for="(item, index) in pageItem.case_item_model"
|
||||
:key="index"
|
||||
>
|
||||
<div class="titlebox">
|
||||
<img src="../assets/titlebg.png" alt="" />
|
||||
<div class="title">{{ item.model_name }}</div>
|
||||
</div>
|
||||
<div class="descbox">
|
||||
<div class="namebox" v-html="item.content"></div>
|
||||
<!-- <div class="namebox" >
|
||||
<div class="row">
|
||||
<div class="left"> ·姓别:</div>
|
||||
<div class="right">
|
||||
杨**</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="left"> ·姓别:</div>
|
||||
<div class="right">
|
||||
症状:自诉1月前因长期熬夜出现软困、乏力,无腹痛,无恶心、呕吐、纳差、胸闷、胸痛、无尿频、尿痛、尿黄,无发热,无胸闷、气紧,无胸痛、心悸,无呼吸困难,无皮肤黄染及皮下出血等。病后饮食稍差,睡眠尚可,精神尚可,大小便正常。,
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<question
|
||||
v-for="(item, index) in pageItem.case_item_question"
|
||||
:key="'case' + pageIndex + 'qestion' + item.question_id"
|
||||
:question="item"
|
||||
@checkAnswer="checkAnswer"
|
||||
:pageIndex="pageIndex"
|
||||
:questionIndex="index"
|
||||
v-if="pageItem.case_item_question"
|
||||
></question>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dealbox">
|
||||
<div class="next" @click="switchPage(pageIndex - 1)">上一步</div>
|
||||
<div class="prev" @click="goNext(pageIndex + 1)">下一步</div>
|
||||
</div>
|
||||
<back></back>
|
||||
<c-dialog
|
||||
:message="dialog_message"
|
||||
ref="cdialog"
|
||||
:showCancel="false"
|
||||
></c-dialog>
|
||||
</div>
|
||||
<van-image-preview ref="ImagePreview" v-model:show="showImg" closeable :images="imgList" @change="onChange">
|
||||
|
||||
</van-image-preview>
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive } from "vue";
|
||||
import api from "../api/user.js";
|
||||
import dayjs from "dayjs";
|
||||
//import { showImagePreview } from 'vant';
|
||||
const case_id = ref(null);
|
||||
const imgList = ref([]);
|
||||
const position = ref(0);
|
||||
const showImg = ref(false);
|
||||
const ImagePreview = ref(null);
|
||||
const props = defineProps({
|
||||
pageIndex: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
case_id: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
pageNum: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
start_time: {
|
||||
type: String,
|
||||
default:'',
|
||||
},
|
||||
pageItem: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const unitAnswer = {
|
||||
pageIndex: null,
|
||||
answer: [],
|
||||
};
|
||||
const cdialog = ref(null);
|
||||
const dialog_message = ref("");
|
||||
|
||||
watch(
|
||||
() => props.pageItem,
|
||||
(newVal) => {
|
||||
if (newVal.case_item_question && newVal.case_item_question.length > 0) {
|
||||
for (let i = 0; i < newVal.case_item_question.length; i++) {
|
||||
unitAnswer.answer[i] = "";
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
const emit = defineEmits(["switchPage", "getAllAnswer"]);
|
||||
const switchPage = (index) => {
|
||||
emit("switchPage", index);
|
||||
};
|
||||
const behaviorRecord = (step = "", start_time = "", end_time = "") => {
|
||||
api
|
||||
.behaviorRecord({
|
||||
case_id: props.case_id,
|
||||
step: step,
|
||||
start_time: start_time,
|
||||
end_time: end_time,
|
||||
})
|
||||
.then((res) => {});
|
||||
};
|
||||
|
||||
const checkAnswer = (data) => {
|
||||
//
|
||||
unitAnswer.pageIndex = data.pageIndex;
|
||||
unitAnswer.answer[data.questionIndex] = {
|
||||
answer: data.answer,
|
||||
question_type: data.question_type,
|
||||
question_id: data.questionId,
|
||||
question_name: data.question_name,
|
||||
question_answer: data.question_answer,
|
||||
option_id: data.option_id,
|
||||
error_tips: data.error_tips,
|
||||
is_right_next: data.is_right_next,
|
||||
};
|
||||
// console.log(unitAnswer);
|
||||
// allAnswer[data.pageIndex]=unitAnswer.answer;
|
||||
// console.log(allAnswer);
|
||||
};
|
||||
const fomatObj = (obj) => {
|
||||
let str = "";
|
||||
for (let key in obj) {
|
||||
if (str) {
|
||||
str += `${obj[key]}`;
|
||||
} else {
|
||||
str = `${obj[key]}`;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
};
|
||||
const passNext = () => {
|
||||
let answer = unitAnswer.answer;
|
||||
console.log(answer);
|
||||
let answerForamt = answer.map((item) => {
|
||||
if (item.question_type == 2) {
|
||||
return {
|
||||
answer: fomatObj(item.answer),
|
||||
question_type: item.question_type,
|
||||
question_id: item.question_id,
|
||||
question_name: item.question_name,
|
||||
question_answer: item.question_answer,
|
||||
option_id: item.option_id,
|
||||
error_tips: item.error_tips,
|
||||
is_right_next: item.is_right_next,
|
||||
};
|
||||
} else {
|
||||
return { ...item };
|
||||
}
|
||||
});
|
||||
console.log(answerForamt);
|
||||
if (answerForamt.length == 0 && props.pageItem.case_item_question) {
|
||||
dialog_message.value = "请回答本页所有问题后再提交";
|
||||
cdialog.value.openDialog();
|
||||
//showToast('请回答本页所有问题后再提交')
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < answerForamt.length; i++) {
|
||||
if (!answerForamt[i].answer) {
|
||||
dialog_message.value = "请回答本页第" + (i + 1) + "个问题后再提交";
|
||||
cdialog.value.openDialog();
|
||||
//showToast('请回答本页第'+(i+1)+'个问题后再提交')
|
||||
return false;
|
||||
}
|
||||
|
||||
if (answerForamt[i].question_type == 2) {
|
||||
if (answerForamt[i].answer.length < 2) {
|
||||
dialog_message.value = answerForamt[i].question_name + "至少选择两项";
|
||||
cdialog.value.openDialog();
|
||||
//showToast('本页第'+(i+1)+'个问题是多选')
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
answerForamt[i].answer !== answerForamt[i].question_answer &&
|
||||
answerForamt[i].is_right_next == 1 &&
|
||||
answerForamt[i].question_type != 3
|
||||
) {
|
||||
//dialog_message.value=props.pageItem.error_tips;
|
||||
dialog_message.value = answerForamt[i].error_tips;
|
||||
cdialog.value.openDialog();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// alert(unitAnswer.pageIndex);
|
||||
// allAnswer[unitAnswer.pageIndex]=answerForamt;
|
||||
// console.log('allAnswer');
|
||||
// console.log(allAnswer);
|
||||
emit("getAllAnswer", {
|
||||
pageIndex: unitAnswer.pageIndex,
|
||||
answer: answerForamt,
|
||||
});
|
||||
return true;
|
||||
};
|
||||
const reportQuestion = (start, end) => {
|
||||
let answer = unitAnswer.answer;
|
||||
for (let i = 0; i < answer.length; i++) {
|
||||
behaviorRecord(answer[i].question_name, start, end);
|
||||
}
|
||||
};
|
||||
const goNext = (index) => {
|
||||
if (passNext()) {
|
||||
if (index < props.pageNum) {
|
||||
let nextPageTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||
localStorage.setItem("entryPage" + index, nextPageTime);
|
||||
if (index == 1) {
|
||||
let start = dayjs(props.start_time).format("YYYY-MM-DD HH:mm:ss");
|
||||
behaviorRecord("第2页", start, nextPageTime);
|
||||
reportQuestion(start, nextPageTime);
|
||||
} else {
|
||||
let prevPageTime = localStorage.getItem("entryPage" + (index - 1));
|
||||
behaviorRecord(`第${index + 2}页`, prevPageTime, nextPageTime);
|
||||
reportQuestion(prevPageTime, nextPageTime);
|
||||
}
|
||||
|
||||
emit("switchPage", index);
|
||||
} else {
|
||||
let nextPageTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||
localStorage.setItem("entryPage" + index, nextPageTime);
|
||||
localStorage.setItem("lastPage", nextPageTime);
|
||||
if (index == 1 && props.pageNum == 1) {
|
||||
let start = dayjs(props.start_time).format("YYYY-MM-DD HH:mm:ss");
|
||||
behaviorRecord("第2页", start, nextPageTime);
|
||||
reportQuestion(start, nextPageTime);
|
||||
} else {
|
||||
let prevPageTime = localStorage.getItem("entryPage" + (index - 1));
|
||||
behaviorRecord(`第${index + 2}页`, prevPageTime, nextPageTime);
|
||||
reportQuestion(prevPageTime, nextPageTime);
|
||||
}
|
||||
emit("switchPage", index);
|
||||
}
|
||||
}
|
||||
};
|
||||
const showPreview=(index)=> {
|
||||
//if(showImg.value)return;
|
||||
showImg.value=true;
|
||||
position.value=index;
|
||||
setTimeout(()=>{
|
||||
ImagePreview.value.swipeTo(index)
|
||||
})
|
||||
};
|
||||
const handleClick = (e) => {
|
||||
let src=e.target.currentSrc;
|
||||
let index =imgList.value.findIndex((item)=>{
|
||||
if(item==src) return true;
|
||||
});
|
||||
|
||||
showPreview(index)
|
||||
|
||||
};
|
||||
onMounted(async () => {
|
||||
let imgArr = [];
|
||||
await nextTick(() => {
|
||||
const nodeList = document.querySelectorAll("#pagemain"+props.pageIndex+" .namebox img");
|
||||
console.log(nodeList);
|
||||
nodeList.forEach(function (node) {
|
||||
imgArr.push(node.src);
|
||||
node.removeEventListener("click",(e)=>{
|
||||
handleClick(e)
|
||||
});
|
||||
node.addEventListener("click", (e)=>{
|
||||
handleClick(e)
|
||||
});
|
||||
});
|
||||
imgList.value = [...new Set(imgArr)];
|
||||
});
|
||||
});
|
||||
const onChange=(newIndex)=>{
|
||||
position.value = newIndex || 0
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.main {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
.dealbox {
|
||||
margin: 12px 15px 10px;
|
||||
padding-bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.prev,
|
||||
.next {
|
||||
width: 73px;
|
||||
font-size: 14px;
|
||||
color: #43c9c3;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #ffffff;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #43c9c3;
|
||||
}
|
||||
|
||||
.count {
|
||||
:deep() .van-count-down {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
right: 15px;
|
||||
top: 18px;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
height: 31px;
|
||||
padding: 0 8px;
|
||||
background: #43c9c3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 20px 15px;
|
||||
position: relative;
|
||||
|
||||
.page {
|
||||
background: #fff;
|
||||
|
||||
min-height: 100px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #43c9c3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 15px;
|
||||
:deep() img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.descbox {
|
||||
margin-top: 13px;
|
||||
background: #f6feff;
|
||||
border-radius: 8px;
|
||||
padding: 12px 10px;
|
||||
}
|
||||
|
||||
.titlebox {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.namebox {
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: first baseline;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.left {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #43c9c3;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
line-height: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
289
src/views/caseIntro.vue
Normal file
@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="count">
|
||||
{{ countTime }}
|
||||
</div>
|
||||
<div class="main" v-show="showIntro && step==-1">
|
||||
<img src="../assets/bg.png" alt="" class="bg">
|
||||
<div class="content">
|
||||
<img src="../assets/wave.png" alt="" class="top">
|
||||
<img src="../assets/wave.png" alt="" class="xia">
|
||||
<div class="title">
|
||||
{{ caseObj.case_name }}
|
||||
</div>
|
||||
<div class="con" v-html="(casePage[0].case_item_model)[0].content" v-if="casePage.length > 0 && casePage[0].case_item_model">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="button" @click="handleStart" >马上开始</div>
|
||||
</div>
|
||||
</div>
|
||||
<caseDetail v-for="(item, index) in pageList" :pageIndex="index" :step="step" @switchPage="switchPage" :pageItem="item" :pageNum="pageList.length" @getAllAnswer="getAllAnswer" :start_time="start_time" :case_id="case_id"></caseDetail>
|
||||
<comment v-show="!showIntro && step==pageList.length" ref="commentRef" :countTime="countTime" @initPage="initPage" :start_time="entry_time" :allAnswer="allAnswer" :is_welfare="is_welfare"></comment>
|
||||
<totop></totop>
|
||||
<back></back>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref ,reactive,getCurrentInstance} from "vue";
|
||||
const step = ref(-1);
|
||||
const key = ref(0);
|
||||
const showIntro = ref(true);
|
||||
const countTime = ref('00:00');
|
||||
const start_time = ref('');
|
||||
const time = ref(0);
|
||||
const timer = ref(null);
|
||||
const casePage = ref([]);
|
||||
const pageList = ref([]);
|
||||
const entry_time=ref('');
|
||||
const commentRef = ref(null);
|
||||
import dayjs from 'dayjs'
|
||||
import api from '../api/user.js';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { WXSHARE } from "../utils/wxshare-1.6.0";
|
||||
import host from "../utils/host"
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const caseObj = reactive({});
|
||||
const allAnswer = reactive({});
|
||||
const { proxy } = getCurrentInstance();
|
||||
const is_welfare = ref(0);
|
||||
let origin=route.query.source?route.query.source:''
|
||||
const source = ref(origin);
|
||||
const case_id = ref(route.query.case_id);
|
||||
const getDetail = async () => {
|
||||
const { code, data } = await api.getCaseDetail(case_id.value);
|
||||
proxy.$loading.hide();
|
||||
if (code == 200) {
|
||||
document.title = data.case_name;
|
||||
if(data.is_join==1){
|
||||
if(source.value){
|
||||
router.push({
|
||||
path:'/result',
|
||||
query:{
|
||||
case_id:data.case_id,
|
||||
project_id:data.project_id,
|
||||
source:source.value
|
||||
|
||||
}
|
||||
})
|
||||
}else{
|
||||
router.push({
|
||||
path:'/result',
|
||||
query:{
|
||||
case_id:data.case_id,
|
||||
project_id:data.project_id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
is_welfare.value=data.is_welfare;
|
||||
console.log('is_welfare:'+data.is_welfare)
|
||||
Object.assign(caseObj, data)
|
||||
casePage.value = data.case_item;
|
||||
pageList.value = [];
|
||||
for (let i = 1; i < data.case_item.length; i++) {
|
||||
pageList.value.push(data.case_item[i]);
|
||||
}
|
||||
let link=host+'/web/caseIntro?case_id='+case_id.value;
|
||||
WXSHARE(data.case_name,'“佳动例”等你来挑战,精彩福利享不停',link,'');
|
||||
}
|
||||
|
||||
}
|
||||
const behaviorRecord=(step='',start_time='',end_time='')=>{
|
||||
api.behaviorRecord({
|
||||
case_id:case_id.value,
|
||||
step:step,
|
||||
start_time:start_time,
|
||||
end_time:end_time
|
||||
}).then(res=>{
|
||||
|
||||
})
|
||||
}
|
||||
const addZero = (num) => {
|
||||
return num < 10 ? '0' + num : '' + num;
|
||||
}
|
||||
const getAllAnswer=(data)=>{
|
||||
//Object.assign(allAnswer,data)
|
||||
allAnswer[data.pageIndex]=data.answer;
|
||||
commentRef.value.formatAnswer(allAnswer)
|
||||
}
|
||||
const switchPage = (index) => {
|
||||
if(index<0){
|
||||
showIntro.value=true;
|
||||
step.value=-1;
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
}else{
|
||||
step.value=index;
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
}
|
||||
if(index==pageList.value.length){
|
||||
//alert(caseObj.project_id);
|
||||
commentRef.value.init(caseObj.case_id,caseObj.project_id)
|
||||
}
|
||||
|
||||
}
|
||||
const handleCount = () => {
|
||||
let minute = 0;
|
||||
let second = 0;
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
}
|
||||
timer.value = setInterval(() => {
|
||||
time.value = time.value + 1;
|
||||
if (time.value >= 60) {
|
||||
minute = Math.floor(time.value / 60);
|
||||
second = time.value % 60;
|
||||
if (minute >= 99 && second >= 59) {
|
||||
clearInterval(timer.value)
|
||||
}
|
||||
countTime.value = `${addZero(minute)}:${addZero(second)}`;
|
||||
} else {
|
||||
countTime.value = `00:${addZero(time.value)}`;
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
const initPage=()=>{
|
||||
// step.value =-1;
|
||||
// showIntro.value=true;
|
||||
step.value = 0;
|
||||
showIntro.value = false;
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
if(caseObj.case_item.length<=1) {
|
||||
commentRef.value.init(caseObj.case_id,caseObj.project_id)
|
||||
}
|
||||
}
|
||||
const handleStart = () => {
|
||||
step.value = 0;
|
||||
showIntro.value = false;
|
||||
start_time.value =dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
behaviorRecord('点击开始',entry_time.value,dayjs(start_time.value).format('YYYY-MM-DD HH:mm:ss'));
|
||||
behaviorRecord('第1页',entry_time.value,dayjs(start_time.value).format('YYYY-MM-DD HH:mm:ss'));
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
if(caseObj.case_item.length<=1) {
|
||||
commentRef.value.init(caseObj.case_id,caseObj.project_id)
|
||||
}
|
||||
}
|
||||
onMounted(async() => {
|
||||
proxy.$loading.show();
|
||||
entry_time.value=dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
getDetail();
|
||||
behaviorRecord('进入问卷',entry_time.value,entry_time.value);
|
||||
handleCount();
|
||||
// await setTimeout(() => {
|
||||
// const nodeList = document.querySelectorAll(".pagemain .namebox img");
|
||||
// console.log(nodeList);
|
||||
// nodeList.forEach(function (node) {
|
||||
// imgList.value.push(node.src);
|
||||
// node.onClick=null;
|
||||
// // node.removeEventListener("click",(e)=>{
|
||||
// // handleClick(e)
|
||||
// // });
|
||||
// node.addEventListener("click", (e)=>{
|
||||
// handleClick(e)
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
clearInterval(timer.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.count {
|
||||
color:#fff;
|
||||
right: 15px;
|
||||
top: 12px;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
height: 31px;
|
||||
padding: 0 8px;
|
||||
background: #43C9C3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: #fff;
|
||||
position: relative;
|
||||
margin: 20px 15px;
|
||||
min-height: 300px;
|
||||
margin-bottom: 80px;
|
||||
border-left: 1px solid #43C9C3;
|
||||
border-right: 1px solid #43C9C3;
|
||||
|
||||
.con {
|
||||
margin: 0 10px;
|
||||
:deep() img {
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 20px 0;
|
||||
font-weight: 500;
|
||||
margin: 0 30px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.top {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
}
|
||||
|
||||
.xia {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
transform: rotate(180deg);
|
||||
bottom: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: fixed;
|
||||
height: 49px;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.button {
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
background: #43C9C3;
|
||||
border-radius: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
95
src/views/caseList.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="banner">
|
||||
<van-image width="100%" height="211" fit="cover" :src="img_url" />
|
||||
<div class="casenum" v-if="case_num>0">
|
||||
病例数:{{ case_num }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<van-tabs color="#0984FD" title-inactive-color="#666666" v-model:active="activeName" sticky offset-top="0">
|
||||
<van-tab title="未参与" :name="2">
|
||||
<div class="tabcon">
|
||||
<c-list :is_take_part="2" ></c-list>
|
||||
</div>
|
||||
</van-tab>
|
||||
<van-tab title="已参与" :name="1">
|
||||
<c-list :is_take_part="1" ></c-list>
|
||||
</van-tab>
|
||||
<van-tab title="全部" :name="0">
|
||||
<c-list :is_take_part="0" ></c-list>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref} from "vue";
|
||||
import { useRoute } from 'vue-router';
|
||||
import { WXSHARE } from "../utils/wxshare-1.6.0";
|
||||
import host from "../utils/host"
|
||||
const route = useRoute();
|
||||
//0:全部 1:已参与 2:未参与
|
||||
const activeName = ref(2);
|
||||
const img_url=ref(route.query.img_url)
|
||||
const case_num=ref(route.query.case_num)
|
||||
onMounted(() => {
|
||||
let link=host+'/web/home';
|
||||
WXSHARE('“佳动例”等你来挑战,精彩福利享不停',"肝胆相照-肝胆病在线公共服务平台",link,'');
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
.banner{
|
||||
position: relative;
|
||||
.casenum {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 3;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
height: 2000px;
|
||||
margin: 0 15px;
|
||||
|
||||
.cell {
|
||||
margin-top: 12px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.casenum {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 3;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.mark {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
height: 21px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
494
src/views/comment.vue
Normal file
@ -0,0 +1,494 @@
|
||||
<template>
|
||||
<div class="main commentmain">
|
||||
<img src="../assets/bg.png" alt="" class="bg">
|
||||
<div class="content">
|
||||
<div class="title">{{ !isResult?'互动讨论区':'留言' }}<img src="../assets/cai.png" alt="" srcset="" class="cai"></div>
|
||||
<div class="tips" v-if="!isResult">感谢您的参与,请在文末点击“完成”提交</div>
|
||||
<div class="conmmentbox">
|
||||
<div class="commentwrapercell">
|
||||
<comment-list :childList="list" @freshLike="freshLike" :case_id="case_id" :project_id="project_id" @freshSecComment="freshSecComment" @handleFreshList="handleFreshList"></comment-list>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="loadmore" v-if="list.length<total" @click="loadMore">——加载更多留言({{total-list.length}}条)—— </div>
|
||||
<div class="add" v-if="isResult" @click="showLiuyan=true">添加留言</div>
|
||||
|
||||
|
||||
<div class="bottom" v-if="!isResult">
|
||||
<div class="textbox">
|
||||
<van-field :autosize="{ minHeight: 150 }" v-model="message" rows="2" autosize type="textarea"
|
||||
maxlength="200" :placeholder="placeholder" show-word-limit />
|
||||
</div>
|
||||
<button class="button" @click="handleSubmit">完成</button>
|
||||
</div>
|
||||
<div class="bottom" v-if="showLiuyan">
|
||||
<div class="textbox">
|
||||
<van-field :autosize="{ minHeight: 150 }" v-model="message" rows="2" autosize type="textarea"
|
||||
maxlength="200" placeholder="病例有疑问?方案有争议?欢迎在此留言、提问、探讨~ " show-word-limit />
|
||||
</div>
|
||||
<button class="button" :disabled="isLock" @click="handleAdd">完成</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<c-dialog :message="dialog_message" ref="cdialog" @handledConfirm="handledConfirm" @handledCancel="handledCancel"></c-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { showToast } from "vant";
|
||||
import { ref,getCurrentInstance } from "vue";
|
||||
import dayjs from 'dayjs'
|
||||
import api from '../api/user.js';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
let share_user_iden_temp=route.query.share_user_iden?route.query.share_user_iden:'';
|
||||
const share_user_iden=ref(share_user_iden_temp);
|
||||
|
||||
const showLiuyan=ref(false);
|
||||
const isResult=ref(route.path.includes('result')?true:false);
|
||||
const read_duration=ref(0);
|
||||
const case_id = ref(route.query.case_id)
|
||||
const isLock=ref(false);
|
||||
const project_id=ref(null);
|
||||
const message = ref("");
|
||||
const cdialog=ref(null);
|
||||
const list=ref([]);
|
||||
const page=ref(1);
|
||||
const total=ref(0);
|
||||
const dialogType=ref(0); //1 未留言,不满3min 2未留言,已满3min 3已留言不满3min
|
||||
const dialog_message=ref('');
|
||||
const placeholder=ref('');
|
||||
const complete_read=ref(0);//完成阅读积分
|
||||
const complete_read_time=ref(0);//完成阅读时间积分
|
||||
const first_high_quality=ref(0);//首次高质量留言积分
|
||||
const is_white_user=ref(0);
|
||||
let origin=route.query.source?route.query.source:''
|
||||
const source = ref(origin);
|
||||
//const is_welfare=ref(0);
|
||||
let answer=ref([])
|
||||
const props=defineProps({
|
||||
countTime:{
|
||||
type:String,
|
||||
default:'0'
|
||||
},
|
||||
allAnswer:{
|
||||
type:Object,
|
||||
default:{}
|
||||
},
|
||||
is_welfare:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
start_time:{
|
||||
type:String,
|
||||
default:''
|
||||
}
|
||||
});
|
||||
|
||||
const formatAnswer=(data)=>{
|
||||
|
||||
answer.value=[];
|
||||
for(let i in data){
|
||||
data[i].forEach(item => {
|
||||
answer.value.push(item)
|
||||
})
|
||||
}
|
||||
console.log(answer.value)
|
||||
|
||||
}
|
||||
const emit=defineEmits(['initPage']);
|
||||
// watch(()=>props.allAnswer,(newVal)=>{
|
||||
// answer.value=[];
|
||||
// console.log(1111111)
|
||||
// console.log(props.allAnswer)
|
||||
// for(let i in newVal){
|
||||
// console.log(333)
|
||||
// console.log(newVal[i])
|
||||
|
||||
// // newVal[i].forEach(item => {
|
||||
// // answer.value.push(item)
|
||||
// // })
|
||||
// }
|
||||
// console.log(answer.value)
|
||||
|
||||
// },{
|
||||
// immediate:true,
|
||||
// deep:true
|
||||
|
||||
// })
|
||||
const handleFreshList=(data)=>{
|
||||
list.value=[];
|
||||
getList();
|
||||
}
|
||||
const getList = async (root_id='') => {
|
||||
const { code, data } = await api.getCommentList({
|
||||
case_id:case_id.value,
|
||||
project_id:project_id.value,
|
||||
page:page.value,
|
||||
page_size:10,
|
||||
root_id:root_id
|
||||
})
|
||||
if (code == 200) {
|
||||
list.value = list.value.concat(data.data);
|
||||
total.value=data.total;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const handledConfirm=()=>{
|
||||
if(dialogType.value==1){
|
||||
emit('initPage');
|
||||
}else if(dialogType.value==2){
|
||||
|
||||
}else if(dialogType.value==3){
|
||||
emit('initPage');
|
||||
}
|
||||
}
|
||||
|
||||
const behaviorRecord=(step='',start_time='',end_time='')=>{
|
||||
api.behaviorRecord({
|
||||
case_id:case_id.value,
|
||||
step:step,
|
||||
start_time:start_time,
|
||||
end_time:end_time
|
||||
}).then(res=>{
|
||||
|
||||
})
|
||||
}
|
||||
const changeDialog=(type)=>{
|
||||
let unit='积分';
|
||||
if(source.value){
|
||||
unit='e豆'
|
||||
};
|
||||
if(type==1){
|
||||
dialogType.value=1;
|
||||
dialog_message.value='阅读时长满足'+read_duration.value/60+'分钟可获得'+complete_read.value+unit+'、留言入选优质点评有机会获得'+first_high_quality.value+unit+',是否继续学习?';
|
||||
cdialog.value.openDialog();
|
||||
}else if(type==2){
|
||||
dialogType.value=2;
|
||||
dialog_message.value='留言入选优质点评,有机会获得'+first_high_quality.value+unit+',是否留言?'
|
||||
cdialog.value.openDialog();
|
||||
}else if(type==3){
|
||||
dialogType.value=3;
|
||||
dialog_message.value='阅读时长满足'+read_duration.value/60+'分钟可获得'+complete_read.value+unit+',是否继续学习?'
|
||||
cdialog.value.openDialog();
|
||||
}else{
|
||||
dialogType.value=4;
|
||||
}
|
||||
}
|
||||
|
||||
const loadMore=()=>{
|
||||
page.value++;
|
||||
getList();
|
||||
}
|
||||
const init= async(caseId,projectId)=>{
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
case_id.value=caseId;
|
||||
project_id.value=projectId;
|
||||
if(!project_id.value){
|
||||
const { code, data } = await api.getCaseDetail(case_id.value);
|
||||
if(code==200){
|
||||
project_id.value=data.project_id;
|
||||
}
|
||||
}
|
||||
handleGetConfig();
|
||||
getList();
|
||||
}
|
||||
const freshLike=(data)=>{
|
||||
console.log(data);
|
||||
if(data.parentIndex<0){
|
||||
let cuurent= list.value[data.index]
|
||||
cuurent.like_num+=data.likeNum;
|
||||
if(data.likeNum>0){
|
||||
cuurent.is_like=true;
|
||||
}else{
|
||||
cuurent.is_like=false;
|
||||
}
|
||||
}else{
|
||||
let cuurent=list.value[data.parentIndex].case_comment[data.index];
|
||||
console.log(cuurent);
|
||||
cuurent.like_num+=data.likeNum;
|
||||
if(data.likeNum>0){
|
||||
cuurent.is_like=true;
|
||||
}else{
|
||||
cuurent.is_like=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
const freshSecComment=(data)=>{
|
||||
console.log('freshSecComment')
|
||||
console.log(data);
|
||||
|
||||
list.value[data.commentIndex].case_comment=list.value[data.commentIndex].case_comment.concat(data.commentData)
|
||||
|
||||
|
||||
}
|
||||
|
||||
const handleSubmit=()=>{
|
||||
let countS=props.countTime.split(':');
|
||||
let current=Number(countS[0])*60+Number(countS[1]);
|
||||
console.log('props.is_welfare:'+props.is_welfare)
|
||||
if(props.is_welfare==1 && is_white_user.value==1){
|
||||
if(message.value==='' && current<read_duration.value){
|
||||
changeDialog(1)
|
||||
}else if(message.value==='' && current>=read_duration.value){
|
||||
changeDialog(2)
|
||||
}else if(message.value && current<read_duration.value){
|
||||
changeDialog(3)
|
||||
}else{
|
||||
handleComplete()
|
||||
}
|
||||
}else{
|
||||
handleComplete()
|
||||
}
|
||||
|
||||
}
|
||||
const handleAdd=async()=>{
|
||||
if(message.value==''){
|
||||
showToast('请输入内容');
|
||||
return false
|
||||
}
|
||||
isLock.value=true;
|
||||
const {code,data}=await api.addComment({
|
||||
case_id:case_id.value,
|
||||
project_id:project_id.value,
|
||||
content:message.value,
|
||||
level:1,
|
||||
root_id:'',
|
||||
parent_id:''
|
||||
})
|
||||
isLock.value=false;
|
||||
if(code==200){
|
||||
handleFreshList()
|
||||
message.value='';
|
||||
showToast('留言成功')
|
||||
}
|
||||
}
|
||||
const handledCancel=()=>{
|
||||
|
||||
handleComplete();
|
||||
};
|
||||
const handleComplete= async()=>{
|
||||
proxy.$loading.show();
|
||||
const {code,data}=await api.completeCase(case_id.value,{
|
||||
project_id:project_id.value,
|
||||
content:message.value,
|
||||
share_user_iden:share_user_iden.value,
|
||||
start_read:dayjs(props.start_time).format('YYYY-MM-DD HH:mm:ss'),
|
||||
end_read:dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
answer:answer.value
|
||||
})
|
||||
if(code==200){
|
||||
let last=localStorage.getItem('lastPage')
|
||||
behaviorRecord('完成',last,dayjs().format('YYYY-MM-DD HH:mm:ss'));
|
||||
if(source.value){
|
||||
router.push({
|
||||
path:'/result',
|
||||
query:{
|
||||
case_id:case_id.value,
|
||||
project_id:project_id.value,
|
||||
source:source.value
|
||||
}
|
||||
});
|
||||
}else{
|
||||
router.push({
|
||||
path:'/result',
|
||||
query:{
|
||||
case_id:case_id.value,
|
||||
project_id:project_id.value
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
proxy.$loading.hide();
|
||||
}
|
||||
const handleGetConfig=async()=>{
|
||||
const {code,data}=await api.getConfig({
|
||||
project_id:project_id.value,
|
||||
});
|
||||
if(code==200){
|
||||
read_duration.value=data.read_duration;
|
||||
complete_read.value=data.complete_read;
|
||||
complete_read_time.value=data.complete_read_time;
|
||||
first_high_quality.value=data.first_high_quality;
|
||||
is_white_user.value=data.is_white_user;
|
||||
if(data.is_white_user==1){
|
||||
let txt='获取奖励';
|
||||
if(source.value){
|
||||
txt='获取e豆'
|
||||
}
|
||||
placeholder.value=`欢迎就本病例提出您的讨论话题、思考与诊疗分享,如病例疑难点、诊疗经验、用药心得等。(病例阅读时长≥${data.read_duration/60}分钟、留言入选精选留言均有机会${txt})`
|
||||
|
||||
}else{
|
||||
placeholder.value=`欢迎就本病例提出您的讨论话题、思考与诊疗分享,如病例疑难点、诊疗经验、用药心得等。`
|
||||
}
|
||||
|
||||
// if(data.read_duration==0){
|
||||
// changeDialog(1)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
//defineExpose({freshLike})
|
||||
|
||||
defineExpose({init,formatAnswer})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.commentmain{
|
||||
:deep(.van-field__control::placeholder){
|
||||
color:#666;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.add {
|
||||
margin: 25px auto;
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
background: #43C9C3;
|
||||
border-radius: 23px;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loadmore {
|
||||
margin-top: 15px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #0CAF98;
|
||||
}
|
||||
|
||||
.conmmentbox {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
|
||||
.expand {
|
||||
width: 240px;
|
||||
height: 19px;
|
||||
margin: 12px auto 12px;
|
||||
background: #43C9C3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
.textbox {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #43C9C3;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
margin: 20px 15px;
|
||||
min-height: 120px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.count {
|
||||
:deep() .van-count-down {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
right:0;
|
||||
top:-10px;
|
||||
z-index:9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
height: 31px;
|
||||
padding:0 8px;
|
||||
background: #43C9C3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 20px 0 10px;
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
font-size: 23px;
|
||||
color: #000000;
|
||||
.cai{
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
bottom:4px;
|
||||
left:-4px;
|
||||
z-index:-1;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.bottom {
|
||||
margin-top: 65px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
|
||||
.button {
|
||||
outline: none;
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
margin: 34px auto 0;
|
||||
background: #43C9C3;
|
||||
border-radius: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
108
src/views/home.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="box" >
|
||||
<van-list v-model:loading="loading" :finished="finished" finished-text="" @load="onLoad" >
|
||||
<div class="row" v-for="(item, index) in list" :key="item.project_id" @click="goCase(item.project_id,item.project_image,item.case_count)">
|
||||
<div class="cell">
|
||||
<div class="mark">
|
||||
<img src="../assets/newicon.png" alt="" v-if="item.is_recently_update==1">
|
||||
<img src="../assets/fuli.png" alt="" v-if="item.is_welfare==1">
|
||||
</div>
|
||||
<div class="casenum">
|
||||
病例数:{{ item.case_count }}
|
||||
</div>
|
||||
<van-image lazy-load radius="8" width="100%" height="194" fit="cover" :src="item.project_image" />
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</div>
|
||||
<div class="nodata" v-if="list.length == 0">
|
||||
暂无数据!
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import api from '../api/user.js';
|
||||
import { ref } from "vue";
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { WXSHARE } from "../utils/wxshare-1.6.0";
|
||||
import host from "../utils/host"
|
||||
const router = useRouter();
|
||||
const page = ref(0);
|
||||
const list = ref([]);
|
||||
const loading = ref(false);
|
||||
const finished = ref(false);
|
||||
const goCase = (id,img,num) => {
|
||||
router.push({
|
||||
path: 'caseList',
|
||||
query: { project_id: id,img_url:img,case_num: num}
|
||||
})
|
||||
}
|
||||
const getList = async () => {
|
||||
const {data,code}=await api.getProjectList({
|
||||
page:page.value,
|
||||
page_size:10,
|
||||
})
|
||||
loading.value = false;
|
||||
if (code == 200) {
|
||||
console.log(data);
|
||||
list.value = list.value.concat(data.data);
|
||||
if (data.data.length <10) {
|
||||
finished.value = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
const onLoad = () => {
|
||||
if(!finished.value) {
|
||||
page.value++;
|
||||
getList();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
onMounted(() => {
|
||||
let link=host+'/web/home';
|
||||
WXSHARE('“佳动例”等你来挑战,精彩福利享不停',"肝胆相照-肝胆病在线公共服务平台",link,'');
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.main {
|
||||
.row {
|
||||
margin: 0 15px;
|
||||
|
||||
.cell {
|
||||
margin-top: 12px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.casenum {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 3;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.mark {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
height: 21px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
308
src/views/pageunit.vue
Normal file
@ -0,0 +1,308 @@
|
||||
<template>
|
||||
<div class="main" :id="'resultmain'+pageIndex" >
|
||||
<!-- <img src="../assets/bg.png" alt="" class="bg">
|
||||
<div class="dealbox">
|
||||
<div class="prev" @click="switchPage(pageIndex-1)">上一步</div>
|
||||
</div> -->
|
||||
<div class="content">
|
||||
|
||||
<div class="pagebox">
|
||||
<div class="page">
|
||||
<div class="card" v-for="(item,index) in pageItem.case_item_model" :key="index">
|
||||
<div class="titlebox">
|
||||
<img src="../assets/titlebg.png" alt="">
|
||||
<div class="title">{{ item.model_name }} </div>
|
||||
</div>
|
||||
<div class="descbox">
|
||||
<div class="namebox" v-html="item.content"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="card" v-html="pageItem.content"></div> -->
|
||||
<!-- <div class="card">
|
||||
<div class="titlebox">
|
||||
<img src="../assets/titlebg.png" alt="">
|
||||
<div class="title">基础信息 </div>
|
||||
</div>
|
||||
<div class="descbox">
|
||||
<div class="namebox">
|
||||
<div class="row">
|
||||
<div class="left"> ·姓别:</div>
|
||||
<div class="right">
|
||||
杨**</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="left"> ·姓别:</div>
|
||||
<div class="right">
|
||||
症状:自诉1月前因长期熬夜出现软困、乏力,无腹痛,无恶心、呕吐、纳差、胸闷、胸痛、无尿频、尿痛、尿黄,无发热,无胸闷、气紧,无胸痛、心悸,无呼吸困难,无皮肤黄染及皮下出血等。病后饮食稍差,睡眠尚可,精神尚可,大小便正常。,
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<questionend v-for="(item,index) in pageItem.case_item_question" :key="'case'+pageIndex+'qestion'+item.question_id" :question="item" @checkAnswer="checkAnswer" :pageIndex="pageIndex" :questionIndex="index" v-if="pageItem.case_item_question"></questionend>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- <div class="dealbox">
|
||||
<div class="next" @click="switchPage(pageIndex-1)">上一步</div>
|
||||
<div class="prev" @click="goNext(pageIndex+1)" >下一步</div>
|
||||
</div> -->
|
||||
<!-- <back></back> -->
|
||||
</div>
|
||||
<van-image-preview ref="ImagePreview" v-model:show="showImg" closeable :images="imgList" @change="onChange">
|
||||
|
||||
</van-image-preview>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
//import { showImagePreview } from 'vant';
|
||||
//const isResult=ref(route.path.includes('result')?true:false);
|
||||
const props=defineProps({
|
||||
pageIndex: {
|
||||
type: Number,
|
||||
default:0
|
||||
},
|
||||
imgList:{
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
step:{
|
||||
type: Number,
|
||||
default:0
|
||||
},
|
||||
pageNum: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
pageItem: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const unitAnswer=reactive({
|
||||
pageIndex:null,
|
||||
answer:[],
|
||||
});
|
||||
const showImg = ref(false);
|
||||
const position = ref(0);
|
||||
const ImagePreview = ref(null);
|
||||
watch(()=>props.pageItem,(newVal)=>{
|
||||
if(newVal.case_item_question.length>0) {
|
||||
for(let i=0;i<newVal.case_item_question.length;i++){
|
||||
unitAnswer.answer[i]=''
|
||||
}
|
||||
}
|
||||
},{
|
||||
immediate:true,
|
||||
deep:true
|
||||
|
||||
})
|
||||
const emit=defineEmits(['switchPage','changeImg']);
|
||||
const switchPage=(index)=>{
|
||||
emit('switchPage',index)
|
||||
}
|
||||
|
||||
const checkAnswer=(data)=>{
|
||||
console.log(data);
|
||||
unitAnswer.pageIndex=data.questionIndex;
|
||||
unitAnswer.answer[data.questionIndex]={answer:data.answer,questin_type:data.question_type,question_id:data.question_id};
|
||||
}
|
||||
const passNext=()=>{
|
||||
let answer=unitAnswer.answer;
|
||||
console.log(answer);
|
||||
if(answer.length==0) {
|
||||
showToast('请回答本页所有问题后再提交')
|
||||
return
|
||||
};
|
||||
for(let i=0;i<answer.length;i++){
|
||||
if(!answer[i].answer){
|
||||
showToast('请回答本页第'+(i+1)+'个问题后再提交')
|
||||
return
|
||||
}
|
||||
if(answer[i].questin_type==2){
|
||||
if(answer[i].answer.length<2){
|
||||
showToast('本页第'+(i+1)+'个问题是多选')
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
const goNext=(index)=>{
|
||||
if(index<props.pageNum){
|
||||
emit('switchPage',index)
|
||||
}else{
|
||||
emit('switchPage',index)
|
||||
passNext()
|
||||
}
|
||||
}
|
||||
const showPreview=(index)=> {
|
||||
showImg.value=true;
|
||||
position.value=index;
|
||||
setTimeout(()=>{
|
||||
ImagePreview.value.swipeTo(index)
|
||||
})
|
||||
};
|
||||
const handleClick = (e) => {
|
||||
|
||||
let src=e.target.currentSrc;
|
||||
console.log(src);
|
||||
console.log(props.imgList);
|
||||
let index =props.imgList.findIndex((item)=>{
|
||||
if(item==src) return true;
|
||||
});
|
||||
showPreview(index)
|
||||
|
||||
};
|
||||
const onChange=(newIndex)=>{
|
||||
position.value = newIndex || 0
|
||||
}
|
||||
onMounted(async()=>{
|
||||
let imgArr=[];
|
||||
nextTick(() => {
|
||||
const nodeList = document.querySelectorAll("#resultmain"+props.pageIndex+" .namebox img");
|
||||
//console.log(nodeList)
|
||||
nodeList.forEach(function (node) {
|
||||
imgArr.push(node.src);
|
||||
node.removeEventListener("click",()=>{
|
||||
handleClick()
|
||||
});
|
||||
node.addEventListener("click", (e)=>{
|
||||
handleClick(e)
|
||||
});
|
||||
});
|
||||
let temp= [...new Set(imgArr)];
|
||||
emit('changeImg',temp)
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.main {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
.dealbox{
|
||||
margin:12px 15px 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.prev,.next {
|
||||
|
||||
width: 73px;
|
||||
font-size: 14px;
|
||||
color: #43C9C3;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #43C9C3;
|
||||
}
|
||||
|
||||
.count {
|
||||
:deep() .van-count-down {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
right:15px;
|
||||
top:18px;
|
||||
z-index:9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
height: 31px;
|
||||
padding:0 8px;
|
||||
background: #43C9C3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 20px 15px;
|
||||
position: relative;
|
||||
|
||||
.page {
|
||||
background: #fff;
|
||||
|
||||
|
||||
min-height: 180px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #43C9C3;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 15px;
|
||||
:deep() img{
|
||||
width:100%;
|
||||
}
|
||||
.descbox {
|
||||
margin-top: 13px;
|
||||
background: #F6FEFF;
|
||||
border-radius: 8px;
|
||||
padding: 12px 10px;
|
||||
}
|
||||
|
||||
.titlebox {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.namebox {
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: first baseline;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.left {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #43C9C3;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
line-height: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
432
src/views/result.vue
Normal file
@ -0,0 +1,432 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="bannerbox">
|
||||
<img src="../assets/banner.jpg" alt="" class="banner">
|
||||
<div class="thank" :class="{'on':!scoreObj.describe}">感谢您完成阅读!</div>
|
||||
<div class="score" v-if="scoreObj.describe">您已获得:<span>{{ scoreObj.total_score }}</span>{{source?'e豆':'积分'}}</div>
|
||||
<div class="tips" v-if="scoreObj.describe">({{scoreObj.describe}})</div>
|
||||
</div>
|
||||
<comment ref="commentRef"></comment>
|
||||
<div class="pagebox">
|
||||
<pageunit v-for="(item, index) in pageList" :pageIndex="index" :pageItem="item" :imgList="imgList" @changeImg="changeImg"></pageunit>
|
||||
</div>
|
||||
<totop></totop>
|
||||
<back></back>
|
||||
</div>
|
||||
<!-- <van-image-preview ref="ImagePreview" v-model:show="showImg" closeable :images="imgList" @change="onChange">
|
||||
|
||||
</van-image-preview> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,reactive } from "vue";
|
||||
import api from '../api/user.js';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { WXSHARE } from "../utils/wxshare-1.6.0";
|
||||
import host from "../utils/host"
|
||||
const scoreObj = reactive({});
|
||||
const route = useRoute();
|
||||
const case_id = ref(route.query.case_id)
|
||||
const pageList = ref([]);
|
||||
const commentRef = ref(null);
|
||||
const project_id = ref(route.query.project_id);
|
||||
const is_welfare=ref(0);
|
||||
const imgList = ref([]);
|
||||
let origin=route.query.source?route.query.source:''
|
||||
const source = ref(origin);
|
||||
|
||||
const getDetail = async () => {
|
||||
const { code, data } = await api.getCaseDetail(case_id.value)
|
||||
if (code == 200) {
|
||||
document.title = data.case_name;
|
||||
let link=host+'/web/caseIntro?case_id='+case_id.value;
|
||||
WXSHARE(data.case_name,'“佳动例”等你来挑战,精彩福利享不停',link,'');
|
||||
// Object.assign(caseObj, data)
|
||||
// casePage.value = data.case_item;
|
||||
pageList.value = [];
|
||||
for (let i = 1; i < data.case_item.length; i++) {
|
||||
pageList.value.push(data.case_item[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const getScore=()=>{
|
||||
api.getScore({
|
||||
case_id:case_id.value
|
||||
}).then(res=>{
|
||||
if(res.code==200){
|
||||
if(res.data){
|
||||
Object.assign(scoreObj, res.data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const changeImg=(data)=>{
|
||||
console.log(data);
|
||||
imgList.value=imgList.value.concat(data);
|
||||
}
|
||||
onMounted(async() => {
|
||||
commentRef.value.init(case_id.value, project_id.value);
|
||||
getScore();
|
||||
getDetail()
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.main {
|
||||
width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.banner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bannerbox {
|
||||
position: relative;
|
||||
|
||||
.thank {
|
||||
position: absolute;
|
||||
top: 21.69%;
|
||||
// right: 18.53%;
|
||||
white-space: nowrap;
|
||||
left:50%;
|
||||
transform: translateX(-50%);
|
||||
font-weight: 600;
|
||||
font-size: 23px;
|
||||
color: #0CAF98;
|
||||
line-height: 30px;
|
||||
}
|
||||
.thank.on{
|
||||
top: 40.10%;
|
||||
}
|
||||
.score {
|
||||
position: absolute;
|
||||
top: 50.10%;
|
||||
//right: 26.13%;
|
||||
left:50%;
|
||||
transform: translateX(-50%);
|
||||
font-weight: 550;
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
align-items: first baseline;
|
||||
font-size: 16px;
|
||||
color: #1F1F1F;
|
||||
span{
|
||||
font-size: 21px;
|
||||
font-weight: 550;
|
||||
color:#FF173D
|
||||
}
|
||||
|
||||
}
|
||||
.tips{
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
top: 72.43%;
|
||||
// right: 9.7%;
|
||||
left:50%;
|
||||
transform: translateX(-50%);
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #1F1F1F;
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
margin: 25px auto;
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
background: #43C9C3;
|
||||
border-radius: 23px;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loadmore {
|
||||
margin-top: 15px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #0CAF98;
|
||||
}
|
||||
|
||||
.conmmentbox {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.talkbox {
|
||||
margin: 12px 30px 0px 0;
|
||||
}
|
||||
|
||||
.toolbox {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.cancel {
|
||||
|
||||
height: 38px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #EBEBEB;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #737478;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ok {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #43C9C3;
|
||||
border: 1px solid #43C9C3;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.expand {
|
||||
width: 240px;
|
||||
height: 19px;
|
||||
margin: 12px auto 12px;
|
||||
background: #43C9C3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
.comemntcell {
|
||||
display: flex;
|
||||
|
||||
.descbox {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
// border-bottom: 1px solid #E5E5E5;
|
||||
|
||||
|
||||
.depart {
|
||||
margin-top: 10px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hospital {
|
||||
margin-top: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.date {
|
||||
margin-top: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.comemntcell {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
|
||||
.descbox {
|
||||
border: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
margin-top: 4px;
|
||||
display: flex;
|
||||
|
||||
.text {
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
line-height: 17px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 30px;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background: #43C9C3;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
height: 15px;
|
||||
background: #43C9C3;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
padding: 0 4px;
|
||||
width: 52px;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.namebox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.name {
|
||||
font-size: 17px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.zanbox {
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
align-items: center;
|
||||
margin-right: 40px;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bg {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 15px;
|
||||
background: url('../assets/bg.png') no-repeat 0 0;
|
||||
background-size: 100% auto;
|
||||
margin: 0px 0px;
|
||||
min-height: 300px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.count {
|
||||
:deep() .van-count-down {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
right:0;
|
||||
top:-10px;
|
||||
z-index:9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
height: 31px;
|
||||
padding:0 8px;
|
||||
background: #43C9C3;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
background-size: 50px 15px;
|
||||
padding: 20px 0 10px;
|
||||
font-weight: 600;
|
||||
font-size: 23px;
|
||||
color: #000000;
|
||||
.cai{
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
bottom:4px;
|
||||
left:-4px;
|
||||
z-index:-1;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.textbox {
|
||||
border-radius: 5px;
|
||||
border: .5px solid #43C9C3;
|
||||
|
||||
:deep() .van-cell {
|
||||
background: none;
|
||||
}
|
||||
|
||||
:deep() .van-field__word-limit {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
margin-top: 65px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
|
||||
.button {
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
margin: 34px auto 0;
|
||||
background: #43C9C3;
|
||||
border-radius: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
103
vite.config.js
Normal file
@ -0,0 +1,103 @@
|
||||
import {
|
||||
join
|
||||
} from 'path'
|
||||
import {
|
||||
defineConfig
|
||||
} from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import {
|
||||
VuetifyResolver
|
||||
} from 'unplugin-vue-components/resolvers';
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
import { visualizer } from 'rollup-plugin-visualizer' //查看项目的依赖
|
||||
import { createHtmlPlugin } from 'vite-plugin-html'
|
||||
import { VantResolver } from '@vant/auto-import-resolver';
|
||||
export default defineConfig(({ command }) => {
|
||||
return {
|
||||
base: command === 'build' ? './' : '/web',
|
||||
plugins: [
|
||||
vue(),
|
||||
|
||||
AutoImport({
|
||||
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
|
||||
imports: ['vue'],
|
||||
resolvers: [VantResolver()],
|
||||
}),
|
||||
visualizer({
|
||||
open: false
|
||||
}),
|
||||
// 将下面的添加到plugin下
|
||||
createHtmlPlugin({
|
||||
minify: true,
|
||||
inject: {
|
||||
data: {
|
||||
title: '互动病例',
|
||||
}
|
||||
}
|
||||
}),
|
||||
Components({
|
||||
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
|
||||
dirs: ['src/components', 'src/views'],
|
||||
resolvers: [VantResolver(),VuetifyResolver()],
|
||||
}),
|
||||
],
|
||||
|
||||
build: {
|
||||
assetsInlineLimit: 4096, // 图片转 base64 编码的阈值
|
||||
minify: 'terser',
|
||||
plugins: [
|
||||
viteCompression({
|
||||
threshold: 1024000 // 对大于 1mb 的文件进行压缩
|
||||
}),
|
||||
],
|
||||
// rollup 配置
|
||||
rollupOptions: {
|
||||
output: {
|
||||
chunkFileNames: 'static/js/[name]-[hash].js', // 引入文件名的名称
|
||||
entryFileNames: 'static/js/[name]-[hash].js', // 包的入口文件名称
|
||||
assetFileNames: 'static/[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
|
||||
manualChunks(id) {
|
||||
// 如果不同模块使用的插件基本相同那就尽可能打包在同一个文件中,减少http请求,如果不同模块使用不同插件明显,那就分成不同模块打包。这是一个矛盾体。
|
||||
// 这里使用的是最小化拆分包。如果是前者可以直接选择返回'vendor'。
|
||||
if (id.includes('node_modules')) {
|
||||
return id.toString().split('node_modules/')[1].split('/')[0].toString(); //让打开那个页面,加载那个页面的js ,让之间的关联足够小
|
||||
// return 'vendor' 如果不同模块使用的插件基本相同那就尽可能打包在同一个文件中,减少http请求;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
terserOptions: {
|
||||
compress: {
|
||||
//生产环境时移除console
|
||||
drop_console: false,
|
||||
drop_debugger: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': join(__dirname, 'src'),
|
||||
}
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
port: 1798,
|
||||
//secure: false,
|
||||
proxy: {
|
||||
// '/api': {
|
||||
// target: 'https://vue3.go-admin.dev',
|
||||
// changeOrigin: true, //开启跨域
|
||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||
// },
|
||||
'/api': {
|
||||
target: 'https://prod-vote.igandan.com',
|
||||
changeOrigin: true, //开启跨域
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
}
|
||||
}
|
||||
},
|
||||
publicDir: '/public'
|
||||
}
|
||||
});
|
||||