index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. <template>
  2. <!-- 禁止滚动穿透 -->
  3. <page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
  4. <view class="main">
  5. <view class="one">
  6. <view class="one_1">
  7. <input type="text" v-model="searchInfo.title" @input="toInput" placeholder="搜索标题">
  8. </view>
  9. <view class="one_2">
  10. <button size="mini" class="button" type="primary" @click="toAdd">添加</button>
  11. </view>
  12. </view>
  13. <view class="two">
  14. <scroll-view scroll-y="true" class="scroll-view" @scrolltolower="toPage" @scroll="toScroll">
  15. <view class="list-scroll-view">
  16. <view class="list" v-for="(item, index) in list" :key="index">
  17. <view class="name">{{item.title||'暂无标题'}}</view>
  18. <view class="other textOver">
  19. 来源:{{item.origin||'暂无'}}
  20. </view>
  21. <view class="other textOver">
  22. 创建时间:{{item.create_time||'暂无'}}
  23. </view>
  24. <view class="other textOver">
  25. 是否启用:{{item.is_use == '0' ? '是' : '否'}}
  26. </view>
  27. <view class="button">
  28. <button class="warning" size="mini" type="warn" @tap.stop="toEdit(item)">修改</button>
  29. <button class="danger" size="mini" type="warn" @tap.stop="toDel(item)">删除</button>
  30. </view>
  31. </view>
  32. </view>
  33. <view class="is_bottom" v-if="is_bottom">
  34. <text>{{config.bottom_title||'到底了!'}}</text>
  35. </view>
  36. </scroll-view>
  37. </view>
  38. <!-- 修改/添加信息 -->
  39. <uni-popup ref="popup" background-color="#fff" type="center" :is-mask-click="false" @change="change">
  40. <view class="popup">
  41. <view class="close">
  42. <text>信息管理</text>
  43. <uni-icons @tap="toClose" type="close" size="20"></uni-icons>
  44. </view>
  45. <view class="info">
  46. <scroll-view class="scroll-view" scroll-y="true">
  47. <view class="list-scroll-view">
  48. <view class="info_1">
  49. <uni-forms ref="valiForm" :rules="rules" :modelValue="form" label-width="85">
  50. <uni-forms-item label="标题" required name="title">
  51. <uni-easyinput v-model="form.title" placeholder="请输入标题" />
  52. </uni-forms-item>
  53. <uni-forms-item label="来源" required name="origin">
  54. <uni-easyinput v-model="form.origin" placeholder="请输入来源" />
  55. </uni-forms-item>
  56. <uni-forms-item label="封面图片" required name="img_url">
  57. <upload class='upload' :list="form.img_url" name="img_url" :count="1"
  58. @uplSuc="uplSuc" @uplDel="uplDel">
  59. </upload>
  60. </uni-forms-item>
  61. <uni-forms-item label="内容" required name="content">
  62. <editor style="width: 100%; padding: 10upx;" id="editor"
  63. :placeholder="placeholder" @input="editorChange" @ready="onEditorReady">
  64. </editor>
  65. </uni-forms-item>
  66. <uni-forms-item label="是否启用" name="is_use">
  67. <uni-data-select v-model="form.is_use" :localdata="is_useList"
  68. @change="is_usechange">
  69. </uni-data-select>
  70. </uni-forms-item>
  71. </uni-forms>
  72. <button class="button" size="mini" type="primary"
  73. @click="submit('valiForm')">保存</button>
  74. </view>
  75. </view>
  76. </scroll-view>
  77. </view>
  78. </view>
  79. </uni-popup>
  80. </view>
  81. </template>
  82. <script>
  83. import upload from '../../components/upload/index.vue';
  84. export default {
  85. components: {
  86. upload
  87. },
  88. data() {
  89. return {
  90. user: {},
  91. config: {},
  92. searchInfo: {},
  93. list: [],
  94. total: 0,
  95. skip: 0,
  96. limit: 10,
  97. page: 0,
  98. form: {
  99. img_url: []
  100. },
  101. // 校验规则
  102. rules: {
  103. title: {
  104. rules: [{
  105. required: true,
  106. errorMessage: '标题不能为空'
  107. }]
  108. },
  109. origin: {
  110. rules: [{
  111. required: true,
  112. errorMessage: '来源不能为空'
  113. }]
  114. },
  115. img_url: {
  116. rules: [{
  117. required: true,
  118. errorMessage: '请上传封面图片'
  119. }]
  120. },
  121. },
  122. is_useList: [{
  123. text: '是',
  124. value: '0'
  125. },
  126. {
  127. text: '否',
  128. value: '1'
  129. }
  130. ],
  131. placeholder: '请输入内容',
  132. content: '',
  133. // 数据是否触底
  134. is_bottom: false,
  135. scrollTop: 0,
  136. // 禁止滚动穿透
  137. show: false
  138. }
  139. },
  140. onShow: async function() {
  141. const that = this;
  142. that.clearPage();
  143. await that.searchToken();
  144. await that.searchConfig();
  145. await that.search();
  146. },
  147. onPullDownRefresh: async function() {
  148. const that = this;
  149. that.clearPage();
  150. await that.search();
  151. uni.stopPullDownRefresh();
  152. },
  153. methods: {
  154. // 禁止滚动穿透
  155. change(e) {
  156. const that = this;
  157. that.show = e.show
  158. },
  159. searchToken() {
  160. const that = this;
  161. try {
  162. const res = uni.getStorageSync('token');
  163. if (res) {
  164. const user = that.$jwt(res);
  165. that.$set(that, `user`, user);
  166. }
  167. } catch (e) {}
  168. },
  169. searchConfig() {
  170. const that = this;
  171. try {
  172. const res = uni.getStorageSync('config');
  173. if (res) that.$set(that, `config`, res);
  174. } catch (e) {}
  175. },
  176. async search() {
  177. const that = this;
  178. let user = that.user;
  179. let info = {
  180. skip: that.skip,
  181. limit: that.limit,
  182. }
  183. if (that.user.role == 'Doctor') info.doctor = that.user._id
  184. else info.doctor = that.user.doctor
  185. const res = await that.$api(`/article`, 'GET', {
  186. ...info,
  187. ...that.searchInfo
  188. })
  189. if (res.errcode == '0') {
  190. let list = [...that.list, ...res.data];
  191. that.$set(that, `list`, list)
  192. that.$set(that, `total`, res.total)
  193. } else {
  194. uni.showToast({
  195. title: res.errmsg,
  196. });
  197. }
  198. },
  199. // 输入框
  200. toInput(e) {
  201. const that = this;
  202. if (that.searchInfo.title) that.$set(that.searchInfo, `title`, e.detail.value)
  203. else that.$set(that, `searchInfo`, {})
  204. that.clearPage();
  205. that.search();
  206. },
  207. // 是否使用
  208. is_usechange(is_use) {
  209. const that = this;
  210. that.$set(that.form, `is_use`, is_use);
  211. },
  212. // 富文本
  213. onEditorReady() {
  214. const that = this
  215. uni.createSelectorQuery().select('#editor').context((res) => {
  216. that.editorCtx = res.context
  217. that.editorCtx.setContents({
  218. html: that.form.content || '',
  219. success: (res) => {
  220. // console.log(res)
  221. },
  222. fail: (res) => {
  223. // console.log(res)
  224. },
  225. })
  226. }).exec()
  227. },
  228. editorChange: function(e) {
  229. const that = this
  230. that.$set(that, `content`, e.detail.html || '')
  231. },
  232. // 图片上传
  233. uplSuc(e) {
  234. const that = this;
  235. that.$set(that.form, `${e.name}`, [...that.form[e.name], e.data]);
  236. },
  237. // 图片删除
  238. uplDel(e) {
  239. const that = this;
  240. let data = that.form[e.name];
  241. let arr = data.filter((i, index) => index != e.data.index);
  242. that.$set(that.form, `${e.name}`, arr)
  243. },
  244. // 添加
  245. toAdd() {
  246. const that = this;
  247. that.$refs.popup.open()
  248. },
  249. // 修改
  250. async toEdit(item) {
  251. const that = this;
  252. const res = await that.$api(`/article/${item._id}`, 'GET', {})
  253. if (res.errcode == '0') {
  254. that.$set(that, `form`, res.data)
  255. that.onEditorReady()
  256. that.$refs.popup.open()
  257. } else {
  258. uni.showToast({
  259. title: res.errmsg,
  260. icon: 'none'
  261. });
  262. }
  263. },
  264. // 保存
  265. submit(ref) {
  266. const that = this;
  267. const form = that.form;
  268. that.$refs[ref].validate().then(async data => {
  269. let res;
  270. if (that.user.role == 'Doctor') data.doctor = that.user._id
  271. else data.doctor = that.user.doctor
  272. data.content = that.content
  273. data.create_time = that.getNowDate()
  274. if (form._id) res = await that.$api(`/article/${form._id}`, 'POST', data)
  275. else res = await that.$api(`/article`, 'POST', data)
  276. if (res.errcode == '0') {
  277. uni.showToast({
  278. title: '维护信息成功',
  279. icon: 'none'
  280. })
  281. that.toClose();
  282. that.clearPage();
  283. that.search();
  284. } else {
  285. uni.showToast({
  286. title: res.errmsg,
  287. icon: 'none'
  288. });
  289. }
  290. })
  291. },
  292. // 删除
  293. async toDel(item) {
  294. const that = this;
  295. uni.showModal({
  296. title: '提示',
  297. content: '您确定删除该数据吗?',
  298. success: async function(res) {
  299. if (res.confirm) {
  300. const res = await that.$api(`/article/${item._id||item.id}`, 'DELETE', {})
  301. if (res.errcode == 0) {
  302. that.clearPage();
  303. that.search();
  304. } else {
  305. uni.showToast({
  306. title: res.errmsg,
  307. icon: 'none'
  308. })
  309. }
  310. }
  311. }
  312. });
  313. },
  314. // 关闭弹框
  315. toClose() {
  316. const that = this;
  317. that.$set(that, `form`, {})
  318. that.onEditorReady()
  319. that.$refs.popup.close();
  320. },
  321. // 分页
  322. toPage(e) {
  323. const that = this;
  324. let list = that.list;
  325. let limit = that.limit;
  326. if (that.total > list.length) {
  327. uni.showLoading({
  328. title: '加载中',
  329. mask: true
  330. })
  331. let page = that.page + 1;
  332. that.$set(that, `page`, page)
  333. let skip = page * limit;
  334. that.$set(that, `skip`, skip)
  335. that.search();
  336. uni.hideLoading();
  337. } else that.$set(that, `is_bottom`, true)
  338. },
  339. toScroll(e) {
  340. const that = this;
  341. let up = that.scrollTop;
  342. that.$set(that, `scrollTop`, e.detail.scrollTop);
  343. let num = Math.sign(up - e.detail.scrollTop);
  344. if (num == 1) that.$set(that, `is_bottom`, false);
  345. },
  346. // 清空列表
  347. clearPage() {
  348. const that = this;
  349. that.$set(that, `list`, [])
  350. that.$set(that, `skip`, 0)
  351. that.$set(that, `limit`, 10)
  352. that.$set(that, `page`, 0)
  353. },
  354. // 格式化日对象
  355. getNowDate() {
  356. var date = new Date();
  357. var sign2 = ":";
  358. var year = date.getFullYear() // 年
  359. var month = date.getMonth() + 1; // 月
  360. var day = date.getDate(); // 日
  361. var hour = date.getHours(); // 时
  362. var minutes = date.getMinutes(); // 分
  363. var seconds = date.getSeconds() //秒
  364. var weekArr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'];
  365. var week = weekArr[date.getDay()];
  366. // 给一位数的数据前面加 “0”
  367. if (month >= 1 && month <= 9) {
  368. month = "0" + month;
  369. }
  370. if (day >= 0 && day <= 9) {
  371. day = "0" + day;
  372. }
  373. if (hour >= 0 && hour <= 9) {
  374. hour = "0" + hour;
  375. }
  376. if (minutes >= 0 && minutes <= 9) {
  377. minutes = "0" + minutes;
  378. }
  379. if (seconds >= 0 && seconds <= 9) {
  380. seconds = "0" + seconds;
  381. }
  382. return year + "-" + month + "-" + day + " " + hour + sign2 + minutes + sign2 + seconds;
  383. }
  384. }
  385. }
  386. </script>
  387. <style lang="scss" scoped>
  388. .main {
  389. display: flex;
  390. flex-direction: column;
  391. width: 100vw;
  392. height: 100vh;
  393. .one {
  394. display: flex;
  395. justify-content: center;
  396. align-items: center;
  397. padding: 2vw;
  398. .one_1 {
  399. padding: 0 2vw;
  400. width: 75vw;
  401. input {
  402. padding: 2vw;
  403. background-color: var(--f1Color);
  404. font-size: var(--font14Size);
  405. border-radius: 5px;
  406. }
  407. }
  408. .one_2 {
  409. padding: 2vw 0;
  410. .button {
  411. background-color: var(--f3CColor);
  412. color: var(--mainColor);
  413. }
  414. }
  415. }
  416. .two {
  417. position: relative;
  418. flex-grow: 1;
  419. background-color: var(--f9Color);
  420. .list:first-child {
  421. margin: 2vw;
  422. }
  423. .list {
  424. background-color: var(--mainColor);
  425. border: 1px solid var(--f5Color);
  426. padding: 2vw;
  427. margin: 0 2vw 2vw 2vw;
  428. border-radius: 5px;
  429. .name {
  430. font-size: var(--font14Size);
  431. font-weight: bold;
  432. padding: 2vw 0;
  433. }
  434. .other {
  435. font-size: var(--font12Size);
  436. color: var(--f85Color);
  437. }
  438. .button {
  439. margin: 2vw 0 0 0;
  440. text-align: center;
  441. .warning {
  442. background: var(--f3CColor);
  443. }
  444. .danger {
  445. background: var(--fF0Color);
  446. }
  447. button {
  448. margin: 0 1vw 0 0;
  449. }
  450. }
  451. }
  452. }
  453. .uni-popup {
  454. z-index: 9999 !important;
  455. }
  456. .popup {
  457. display: flex;
  458. flex-direction: column;
  459. width: 90vw;
  460. background-color: var(--f9Color);
  461. .close {
  462. display: flex;
  463. justify-content: space-between;
  464. padding: 2vw;
  465. text:first-child {
  466. font-size: var(--font16Size);
  467. font-weight: bold;
  468. }
  469. }
  470. .info {
  471. position: relative;
  472. height: 40vh;
  473. .info_1 {
  474. display: flex;
  475. flex-direction: column;
  476. align-items: center;
  477. padding: 2vw;
  478. #editor {
  479. width: 100%;
  480. height: 100px;
  481. border: 1px solid #F0F0F0;
  482. }
  483. .button {
  484. margin: 2vw 0 0 0;
  485. background-color: var(--f3CColor);
  486. color: var(--mainColor);
  487. font-size: var(--font14Size);
  488. }
  489. }
  490. }
  491. }
  492. }
  493. .scroll-view {
  494. position: absolute;
  495. top: 0;
  496. left: 0;
  497. right: 0;
  498. bottom: 0;
  499. .list-scroll-view {
  500. display: flex;
  501. flex-direction: column;
  502. }
  503. }
  504. .is_bottom {
  505. width: 100%;
  506. text-align: center;
  507. text {
  508. padding: 2vw 0;
  509. display: inline-block;
  510. color: var(--f85Color);
  511. font-size: var(--font14Size);
  512. }
  513. }
  514. </style>