privacyDialog.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <view class="container" v-if="showDialog">
  3. <view class="mask"></view>
  4. <view class="modal_panel">
  5. <view class="modal_header">
  6. <text>用户隐私保护指引</text>
  7. </view>
  8. <view class="modal_main">
  9. <view class="content_wrapper">
  10. <view>欢迎您使用{{ hosName }}小程序!</view>
  11. <view>
  12. 为了更好保护您的权益,请您在使用我们的产品服务之前,请仔细阅读我们的<text class="link" @click="toViewArticle" :data-articleid="articleId" data-articletitle="隐私政策协议">《隐私政策协议》</text>,以帮助您更好的了解我们对于您的个人信息的保护情况,尤其是以下条款:
  13. </view>
  14. <view>
  15. 1. 我们收集、使用、存储和共享您的个人信息的情况,及您所享有的相关权利;
  16. </view>
  17. <view>
  18. 2. 我们的产品请求与个人信息相关的设备权限的相关信息;
  19. </view>
  20. <view>
  21. 3. 我们的产品接入的第三方SDK相关信息;
  22. </view>
  23. <view>
  24. 4. 我们的限制责任、免责条款。
  25. </view>
  26. <view>
  27. 若您对以上内容(包括我们的协议)有任何疑问的,您可以通过电话联系我们;若同意以上内容,请点击“同意”,开始使用我们的产品及服务。
  28. </view>
  29. <view>
  30. 相关协议:
  31. </view>
  32. <view class="link" @click="toViewArticle" :data-articleid="articleId" data-articletitle="隐私政策协议">
  33. 《隐私政策协议》
  34. </view>
  35. </view>
  36. </view>
  37. <view class="modal_footer">
  38. <view class="modal_btn" @click="handleCancel">暂不使用</view>
  39. <view class="modal_btn modal_btn_confirm" @click="handleConfirm">同意</view>
  40. </view>
  41. </view>
  42. </view>
  43. </template>
  44. <script lang="ts" setup>
  45. import { ref, watch, getCurrentInstance } from 'vue';
  46. import { common } from '@/utils';
  47. // 1. 获取当前组件实例代理
  48. const { proxy } = getCurrentInstance() as any;
  49. // 2. Props 定义
  50. const props = withDefaults(defineProps<{
  51. articleId?: string;
  52. hosName?: string;
  53. currentUser?: any;
  54. }>(), {
  55. articleId: '',
  56. hosName: '',
  57. currentUser: () => ({})
  58. });
  59. // 3. State
  60. const showDialog = ref(false);
  61. // 4. Methods
  62. const changeDialogShown = () => {
  63. showDialog.value = !showDialog.value;
  64. };
  65. /**
  66. * 判断是否展示隐私协议弹窗
  67. */
  68. const getPrivacySetting = () => {
  69. let privacySettingList: any = uni.getStorageSync("PrivacySettingList");
  70. // 未找到同意配置,展示
  71. if (common.isEmpty(privacySettingList)) {
  72. return true;
  73. }
  74. // 无就诊人信息,展示
  75. if (common.isEmpty(props.currentUser) || common.isEmpty(props.currentUser.memberId)) {
  76. return true;
  77. }
  78. try {
  79. privacySettingList = JSON.parse(privacySettingList);
  80. } catch (e) {
  81. console.error('PrivacySettingList parse error', e);
  82. // 解析失败视为未同意
  83. return true;
  84. }
  85. // 未找到当前就诊人授权记录,展示
  86. const target = privacySettingList.find((item: any) => item.authMemberId === props.currentUser.memberId);
  87. if (common.isEmpty(target)) {
  88. return true;
  89. }
  90. return false;
  91. };
  92. /**
  93. * 记录已授权患者
  94. */
  95. const setPrivacySetting = (memberId: string) => {
  96. let privacySettingList: any = uni.getStorageSync("PrivacySettingList");
  97. let list = [];
  98. if (common.isNotEmpty(privacySettingList)) {
  99. try {
  100. list = JSON.parse(privacySettingList);
  101. } catch (e) {
  102. list = [];
  103. }
  104. }
  105. const resPrivacySettingList = [...list, ...[{ authMemberId: memberId }]];
  106. uni.setStorageSync("PrivacySettingList", JSON.stringify(resPrivacySettingList));
  107. };
  108. /**
  109. * 确认按钮
  110. */
  111. const handleConfirm = () => {
  112. changeDialogShown();
  113. if (common.isEmpty(props.currentUser)) {
  114. return;
  115. }
  116. setPrivacySetting(props.currentUser.memberId);
  117. };
  118. /**
  119. * 取消按钮
  120. */
  121. const handleCancel = () => {
  122. common.showToast(`您需要同意隐私政策才能享受我们的服务`, () => {}, 2 * 1000);
  123. };
  124. /**
  125. * 查看政策
  126. */
  127. const toViewArticle = (e: any) => {
  128. // 安全访问 dataset
  129. const dataset = e.currentTarget?.dataset || {};
  130. const { articleid: articleId, articletitle: articleTitle } = dataset;
  131. const queryBean = {
  132. articleId,
  133. articleTitle,
  134. hosName: props.hosName // 使用 props.hosName
  135. };
  136. const url = `/pages/st1/business/otherService/agreementDetail/agreementDetail`;
  137. common.goToUrl(url, { skipWay: 'navigateTo', data: `&queryBean=${encodeURIComponent(JSON.stringify(queryBean))}` });
  138. };
  139. // 5. Watchers
  140. // 对应原 observer(value)
  141. watch(() => props.currentUser, (newVal) => {
  142. showDialog.value = getPrivacySetting();
  143. }, { deep: true, immediate: true });
  144. // 6. Expose
  145. defineExpose({
  146. changeDialogShown
  147. });
  148. </script>
  149. <style lang="scss" scoped>
  150. .container {
  151. position: fixed;
  152. top: 0;
  153. left: 0;
  154. width: 100%;
  155. height: 100%;
  156. z-index: 9999;
  157. }
  158. .mask {
  159. width: inherit;
  160. height: inherit;
  161. background-color: rgba(0, 0, 0, 0.6);
  162. }
  163. .modal_panel {
  164. width: 80%;
  165. min-height: 200upx;
  166. max-height: 65%;
  167. background-color: #fff;
  168. border-radius: 30upx;
  169. overflow: hidden;
  170. position: absolute;
  171. top: 50%;
  172. left: 50%;
  173. transform: translate(-50%, -50%);
  174. display: flex;
  175. flex-direction: column;
  176. align-items: stretch;
  177. justify-content: stretch;
  178. }
  179. .modal_header {
  180. text-align: center;
  181. height: 60upx;
  182. line-height: 60upx;
  183. font-size: 36upx;
  184. padding: 0 20upx;
  185. margin: 40upx 0 30upx;
  186. }
  187. .modal_main {
  188. min-height: 200upx;
  189. overflow: auto;
  190. margin-bottom: 32upx;
  191. padding: 0 30upx;
  192. flex: 1;
  193. }
  194. .modal_main .content_wrapper {
  195. height: fit-content;
  196. }
  197. .modal_main view {
  198. line-height: 55upx;
  199. font-size: 30upx;
  200. }
  201. .modal_footer {
  202. height: 100upx;
  203. line-height: 100upx;
  204. display: flex;
  205. border-top: 2upx solid #ccc;
  206. }
  207. .modal_btn {
  208. flex: 1;
  209. text-align: center;
  210. font-size: 32upx;
  211. height: inherit;
  212. line-height: inherit;
  213. border-right: 2upx solid #ccc;
  214. }
  215. .modal_btn:last-child {
  216. border-right: none;
  217. }
  218. .modal_btn_confirm {
  219. color: var(--dominantColor);
  220. }
  221. .link {
  222. color: var(--dominantColor);
  223. }
  224. </style>