problemReminder.vue 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <Popup v-model:show="show" class="problem-reminder-popup">
  3. <div class="problem-reminder">
  4. <!-- 标题区域 -->
  5. <div class="problem-reminder-header">
  6. <div class="title-section">
  7. <div class="main-title">填写以下问题</div>
  8. <div class="sub-title">为您定制农事提醒</div>
  9. </div>
  10. <img class="header-icon" src="@/assets/img/home/file-icon.png" alt="" />
  11. </div>
  12. <div class="question-section-wrapper">
  13. <span class="question-text">{{ questPopupData.quest }}</span>
  14. <div class="img">
  15. <img :src="questPopupData.backgroundImage" alt="" />
  16. </div>
  17. <div class="options-section">
  18. <span class="options-label">您可以选择</span>
  19. <div class="options-buttons">
  20. <div class="option-btn" @click="toUpload">拍照识别</div>
  21. <div class="option-btn" @click="toPage" v-if="curRole == 0">咨询专家</div>
  22. </div>
  23. </div>
  24. </div>
  25. <!-- 底部按钮区域 -->
  26. <div class="bottom-buttons">
  27. <div
  28. v-for="(opt, idx) in bottomAnswerOptions"
  29. :key="idx"
  30. class="bottom-btn"
  31. :class="{ 'yes-btn': isYesOption(opt), 'no-btn': !isYesOption(opt) }"
  32. @click="onBottomOptionClick(opt)"
  33. >
  34. {{ getOptionLabel(opt) }}
  35. </div>
  36. </div>
  37. <div class="forward-btn bottom-btn" v-if="curRole == 2">转发给客户</div>
  38. </div>
  39. </Popup>
  40. <Popup v-model:show="noShow" class="no-popup">
  41. <div class="no-popup-title">
  42. <span>感谢您的配合</span>
  43. <div class="no-popup-title-sub">飞鸟将会记录下您当前的农场情况</div>
  44. </div>
  45. <div class="no-popup-btn" @click="noShow = false">我知道了</div>
  46. </Popup>
  47. <!-- 农事信息弹窗 -->
  48. <detail-dialog ref="detailDialogRef" :show-success-only="true"></detail-dialog>
  49. <!-- 新增:激活上传弹窗 -->
  50. <active-upload-popup @handleUploadSuccess="handleUploadSuccess"></active-upload-popup>
  51. </template>
  52. <script setup>
  53. import { Popup } from "vant";
  54. import { ref,watch } from "vue";
  55. import wx from "weixin-js-sdk";
  56. import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
  57. import detailDialog from "@/components/detailDialog.vue";
  58. import eventBus from "@/api/eventBus";
  59. import { useRouter } from "vue-router";
  60. const router = useRouter();
  61. const props = defineProps({
  62. farmId: {
  63. type: [Number, String],
  64. default: null,
  65. }
  66. });
  67. const show = ref(false);
  68. const noShow = ref(false);
  69. const dropdownGardenItem = ref({
  70. organId: 93490,
  71. periodId: 1,
  72. wktVal: "wktVal",
  73. address: "address",
  74. district: "district",
  75. name: "荔博园",
  76. });
  77. const toUpload = () => {
  78. wx.miniProgram.navigateTo({
  79. url: `/pages/subPages/carmera/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
  80. });
  81. };
  82. function toPage() {
  83. router.push("/expert_list");
  84. }
  85. const detailDialogRef = ref(null);
  86. const curRole = localStorage.getItem("SET_USER_CUR_ROLE");
  87. watch(() => props.farmId, (newVal) => {
  88. if (newVal) {
  89. fetchQuestPopup();
  90. }
  91. });
  92. const questPopupData = ref({});
  93. const bottomAnswerOptions = ref([]);
  94. const fetchQuestPopup = () => {
  95. VE_API.home
  96. .fetchQuestPopup({ farmId: props.farmId })
  97. .then(({ data }) => {
  98. if (Array.isArray(data) && data.length > 0) {
  99. show.value = true;
  100. questPopupData.value = data[0];
  101. bottomAnswerOptions.value = transformAnswerOptions(questPopupData.value?.answerOptions);
  102. }
  103. })
  104. .catch(() => {});
  105. };
  106. function transformAnswerOptions(raw) {
  107. let parsed = raw;
  108. if (typeof raw === "string") {
  109. try {
  110. parsed = JSON.parse(raw);
  111. } catch (e) {
  112. parsed = [raw];
  113. }
  114. }
  115. if (Array.isArray(parsed)) {
  116. return parsed.map((item) => {
  117. if (item && typeof item === "object") {
  118. const label = item.name;
  119. const value = item.value;
  120. return { label, value };
  121. }
  122. return { label: String(item), value: item };
  123. });
  124. }
  125. return [];
  126. }
  127. function getOptionLabel(opt) {
  128. return opt?.label ?? String(opt ?? "");
  129. }
  130. function isYesOption(opt) {
  131. const label = (opt?.label ?? "").toString();
  132. const value = opt?.value;
  133. if (typeof value === "boolean") return value === true;
  134. if (typeof value === "number") return value === 1;
  135. if (typeof value === "string") {
  136. const v = value.trim().toLowerCase();
  137. if (v === "1" || v === "true" || v === "yes") return true;
  138. }
  139. const yesKeywords = ["是", "yes", "确认", "同意", "有", "发生"];
  140. return yesKeywords.some((k) => label.toLowerCase().includes(k.toLowerCase()));
  141. }
  142. const optValue = ref(null);
  143. function onBottomOptionClick(opt) {
  144. show.value = false;
  145. optValue.value = opt.value;
  146. if (opt.value == 1) {
  147. eventBus.emit("activeUpload:show", {
  148. gardenIdVal: props.farmId,
  149. problemTitleVal: "请选择您出现白点的时间",
  150. typeVal: "question",
  151. });
  152. } else {
  153. saveQuestPopup();
  154. }
  155. }
  156. function saveQuestPopup() {
  157. const agriDate = getTodayStr();
  158. const params = {
  159. farmId: props.farmId,
  160. phenologyId: questPopupData.value.phenologyId,
  161. indicatorId: questPopupData.value.indicatorId,
  162. answerValue: optValue.value,
  163. agriDate: agriDate,
  164. };
  165. params.imagePaths = images.value;
  166. VE_API.home.saveQuestPopup(params).then((res) => {
  167. if (res.code === 0) {
  168. show.value = false;
  169. if (optValue.value != 1) {
  170. noShow.value = true;
  171. }
  172. }
  173. });
  174. }
  175. function getTodayStr() {
  176. const d = new Date();
  177. const y = d.getFullYear();
  178. const m = String(d.getMonth() + 1).padStart(2, "0");
  179. const day = String(d.getDate()).padStart(2, "0");
  180. return `${y}-${m}-${day}`;
  181. }
  182. const images = ref([]);
  183. function handleUploadSuccess(params) {
  184. images.value = params.images;
  185. saveQuestPopup();
  186. detailDialogRef.value.showDialog("708734452137725952", "咨询专家");
  187. }
  188. </script>
  189. <style lang="scss" scoped>
  190. .problem-reminder-popup {
  191. width: 100%;
  192. border-radius: 14px;
  193. padding: 20px 15px;
  194. box-sizing: border-box;
  195. background-image: linear-gradient(180deg, #d1e7fd 0%, #ffffff 25%);
  196. .problem-reminder {
  197. display: flex;
  198. flex-direction: column;
  199. // 标题区域样式
  200. .problem-reminder-header {
  201. display: flex;
  202. justify-content: space-between;
  203. align-items: flex-start;
  204. gap: 15px;
  205. .title-section {
  206. flex: 1;
  207. font-size: 22px;
  208. color: #1d1e1f;
  209. line-height: 1.2;
  210. div {
  211. font-family: "PangMenZhengDao";
  212. }
  213. }
  214. .header-icon {
  215. width: 88px;
  216. height: 88px;
  217. margin-top: -10px;
  218. margin-right: -5px;
  219. }
  220. }
  221. .question-section-wrapper {
  222. border: 1px solid #ececec;
  223. border-radius: 8px;
  224. padding: 10px 8px;
  225. margin-top: -10px;
  226. background-color: #fff;
  227. .question-text {
  228. font-size: 16px;
  229. color: #252525;
  230. font-weight: 500;
  231. }
  232. .img {
  233. margin: 12px 0;
  234. width: 100%;
  235. height: 140px;
  236. img {
  237. width: 100%;
  238. height: 100%;
  239. border-radius: 6px;
  240. object-fit: cover;
  241. }
  242. }
  243. .options-section {
  244. display: flex;
  245. align-items: center;
  246. justify-content: space-between;
  247. background-color: rgba(33, 153, 248, 0.1);
  248. border-radius: 8px;
  249. padding: 7px 8px;
  250. font-weight: 500;
  251. .options-label {
  252. font-size: 14px;
  253. color: #2199f8;
  254. }
  255. .options-buttons {
  256. display: flex;
  257. flex-wrap: wrap;
  258. gap: 10px;
  259. .option-btn {
  260. padding: 5px 14px;
  261. border-radius: 20px;
  262. background: #fff;
  263. color: #252525;
  264. flex: 1;
  265. }
  266. }
  267. }
  268. }
  269. // 底部按钮区域样式
  270. .bottom-buttons {
  271. display: flex;
  272. gap: 12px;
  273. margin-top: 10px;
  274. }
  275. .forward-btn{
  276. margin-top: 10px;
  277. }
  278. .bottom-btn {
  279. flex: 1;
  280. padding: 8px 0;
  281. border-radius: 25px;
  282. font-size: 16px;
  283. text-align: center;
  284. background: #fff;
  285. border: 1px solid #e5e5e5;
  286. &.yes-btn {
  287. background-image: linear-gradient(180deg, #76c3ff 0%, #2199f8 100%);
  288. color: #fff;
  289. border: none;
  290. }
  291. }
  292. }
  293. }
  294. .no-popup {
  295. width: 76%;
  296. border-radius: 14px;
  297. padding: 28px 15px 20px;
  298. box-sizing: border-box;
  299. .no-popup-title {
  300. font-size: 24px;
  301. font-weight: 500;
  302. text-align: center;
  303. .no-popup-title-sub {
  304. font-size: 16px;
  305. margin-top: 8px;
  306. }
  307. }
  308. .no-popup-btn {
  309. background-color: #2199f8;
  310. padding: 8px;
  311. border-radius: 20px;
  312. color: #fff;
  313. font-size: 16px;
  314. margin-top: 32px;
  315. text-align: center;
  316. }
  317. }
  318. </style>