plan.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <template>
  2. <a-card title="计划模板" >
  3. <table-pro
  4. :service="AiboxCloudController.plan"
  5. :columns="columns"
  6. ref="tableProDom"
  7. @add="openModal"
  8. >
  9. <template #render="{ column, record }">
  10. <template v-if="column.key === 'planUse'">
  11. <a-space>
  12. <a-tag :color="planUseMap.get(record.planUse)?.color" >{{planUseMap.get(record.planUse)?.label}}</a-tag>
  13. </a-space>
  14. </template>
  15. <template v-if="column.key === 'action'">
  16. <a-popconfirm
  17. title="确定要删除这计划吗"
  18. ok-text="Yes"
  19. cancel-text="No"
  20. @confirm="delPlan(record.planNum)"
  21. >
  22. <a>删除</a>
  23. </a-popconfirm>
  24. </template>
  25. </template>
  26. </table-pro>
  27. </a-card>
  28. <modal-pro
  29. style="width: 800px;"
  30. label="新增工作计划"
  31. :open="state.visible"
  32. @cancel="state.visible = false"
  33. destroyOnClose
  34. @ok="onsubmitSchedule"
  35. >
  36. <a-row >
  37. <a-col :span="4">计划名称:</a-col>
  38. <a-col ><a-input v-model:value="state.scheduleName"></a-input></a-col>
  39. </a-row>
  40. <a-row style="margin-top: 20px;" >
  41. <table border="" style="user-select: none;" >
  42. <thead>
  43. <tr>
  44. <td width="100" :rowSpan="2" :colSpan="0" > 星期/时间</td>
  45. <td colSpan="12" style='text-align: center' > 00:00-12:00</td>
  46. <td colSpan="12" style='text-align: center' > 12:00-24:00</td>
  47. </tr>
  48. </thead>
  49. <tbody>
  50. <tr>
  51. <td ></td>
  52. <td
  53. v-for="(item, index) in new Array(24).fill(1)"
  54. :key="index"
  55. width="25"
  56. :col-span="1"
  57. >
  58. {{index >= 10 ? index: "0" + index}}
  59. </td>
  60. </tr>
  61. <tr
  62. :key="i"
  63. v-for="(item , i) in new Array(7).fill(1)"
  64. >
  65. <th > 星期{{calcWeek(String(i + 1))}} </th>
  66. <td
  67. :col-span="1"
  68. v-for="(item, index) in new Array(24).fill(1)"
  69. :key="index"
  70. :time="JSON.stringify({
  71. week: String(i + 1),
  72. hour: calcTime(index)
  73. })"
  74. @mousedown="onMouseDown"
  75. @mouseenter="onMouseEnter"
  76. @mouseup="onMouseUp"
  77. style="cursor: pointer"
  78. ></td>
  79. </tr>
  80. </tbody>
  81. </table>
  82. <a-row style="margin-top: 16px; width: 100%" :gutter="[8, 8]" >
  83. <a-col> <a-row> <div style="width: 15px;height: 30px; border: 1px solid #ccc; margin-right: 5px" ></div> 未选</a-row> </a-col>
  84. <a-col> <a-row> <div style="width: 15px;height: 30px; background-color: skyblue; margin-right: 5px" > </div> 已选</a-row> </a-col>
  85. <a-row style="margin-top: 20px; width: 100%" >
  86. <a-col :span="24" :key="item.week" v-for="item in state.selectTime" >
  87. <a-row :gutter="[8, 8]">
  88. <a-col :span="4" >星期{{calcWeek(item.week)}}:</a-col>
  89. <a-col :span="20" >
  90. <a-row :guttr="[8, 2]" >
  91. <a-col style="margin-right: 5px;" v-for="_ in item.desc" :key="_" >{{_}}</a-col>
  92. </a-row>
  93. </a-col>
  94. </a-row>
  95. </a-col>
  96. </a-row>
  97. </a-row>
  98. </a-row>
  99. </modal-pro>
  100. </template>
  101. <script lang='ts' setup >
  102. import { AiboxCloudController } from '@/controller'
  103. import { message } from 'ant-design-vue'
  104. import { ref, reactive, onMounted, watch, onUnmounted } from 'vue'
  105. const columns = [
  106. {
  107. title: '模版编号',
  108. dataIndex: 'planNum',
  109. key: 'planNum'
  110. },
  111. {
  112. title: '模版状态',
  113. dataIndex: 'planUse',
  114. key: 'planUse'
  115. },
  116. {
  117. title: '模板名称',
  118. dataIndex: 'planName',
  119. key: 'planName'
  120. },
  121. {
  122. title: '模板时间',
  123. dataIndex: 'planTime',
  124. key: 'planTime'
  125. },
  126. {
  127. title: '操作',
  128. dataIndex: 'action',
  129. key: 'action'
  130. }
  131. ]
  132. const weekMap = new Map([
  133. ['1', '一'],
  134. ['2', '二'],
  135. ['3', '三'],
  136. ['4', '四'],
  137. ['5', '五'],
  138. ['6', '六'],
  139. ['7', '天']
  140. ])
  141. const calcWeek = (week: string) => weekMap.get(week)
  142. const calcTime = (index: number) => index < 10 ? '0' + index : index
  143. const calcLtTen = (time: number) => time < 10 ? `0${time}` : time
  144. const tableProDom = ref()
  145. const initSelectTime = [
  146. { week: '1', time: [], desc: [], value: '000000000000000000000000' },
  147. { week: '2', time: [], desc: [], value: '000000000000000000000000' },
  148. { week: '3', time: [], desc: [], value: '000000000000000000000000' },
  149. { week: '4', time: [], desc: [], value: '000000000000000000000000' },
  150. { week: '5', time: [], desc: [], value: '000000000000000000000000' },
  151. { week: '6', time: [], desc: [], value: '000000000000000000000000' },
  152. { week: '7', time: [], desc: [], value: '000000000000000000000000' }
  153. ]
  154. const planUseMap = new Map([
  155. [0, { color: 'volcano', label: '未使用' }],
  156. [1, { color: 'green', label: '使用中' }]
  157. ])
  158. const state = reactive({
  159. loading: false,
  160. visible: false,
  161. selectVisible: false, // 是否开始选择
  162. dataSource: [],
  163. selectTime: JSON.parse(JSON.stringify(initSelectTime)),
  164. scheduleName: ''
  165. })
  166. const delPlan = async (planNum: number) => {
  167. await AiboxCloudController.delPlan(planNum)
  168. tableProDom.value.reload()
  169. }
  170. watch(
  171. () => state.selectVisible,
  172. () => {
  173. const $r = state.selectTime.map(item => {
  174. if (!item.time.length) {
  175. item.desc = []
  176. return item
  177. }
  178. const sortArr = item.time.sort((a, b) => a - b)
  179. let len = 0
  180. let start = sortArr[len]
  181. const r = [[start]]
  182. let col = 0
  183. const _value = item.value.split('')
  184. _value[Number(start)] = '1'
  185. while (len < sortArr.length - 1) {
  186. if (Number(start) + 1 !== Number(sortArr[len + 1])) {
  187. col++
  188. r.push([])
  189. }
  190. start = sortArr[len + 1]
  191. r[col].push(start)
  192. _value[Number(start)] = '1'
  193. len++
  194. }
  195. item.value = _value.join('')
  196. item.desc = r.map(v => {
  197. const isTwentyThree = Number(v[v.length - 1]) === 23 ? -1 : Number(v[v.length - 1])
  198. if (v.length !== 1) {
  199. return `${calcLtTen(Number(v[0]))}: 00 ~ ${calcLtTen(isTwentyThree + 1)}: 00`
  200. } else {
  201. return `${calcLtTen(Number(v[0]))}: 00 ~ ${calcLtTen(isTwentyThree + 1)}: 00`
  202. }
  203. })
  204. return item
  205. })
  206. state.selectTime = $r
  207. // tableProDom.value.reload()
  208. }
  209. )
  210. const onMouseUp = () => {
  211. state.selectVisible = false
  212. }
  213. const onMouseEnter = (e: MouseEvent) => {
  214. if (!state.selectVisible) return
  215. e.target.style.backgroundColor = e.target.style.backgroundColor ? '' : 'skyblue'
  216. const cusAttr = JSON.parse(Array.from(e.target.attributes).find(item => item.name === 'time').nodeValue)
  217. const $r = state.selectTime.map(item => {
  218. if (item.week === cusAttr.week) {
  219. if (e.target.style.backgroundColor) {
  220. item.time.push(cusAttr.hour)
  221. } else {
  222. item.time = item.time.filter(_ => _ !== cusAttr.hour)
  223. }
  224. item.time = Array.from(new Set([...item.time]))
  225. }
  226. return item
  227. })
  228. state.selectTime = $r
  229. }
  230. const onMouseDown = (e) => {
  231. const cusAttr = JSON.parse(Array.from(e.target.attributes).find(item => item.name === 'time').nodeValue)
  232. e.target.style.backgroundColor = e.target.style.backgroundColor ? '' : 'skyblue'
  233. const $r = state.selectTime.map(item => {
  234. if (item.week === cusAttr.week) {
  235. if (e.target.style.backgroundColor) {
  236. item.time.push(cusAttr.hour)
  237. } else {
  238. item.time = item.time.filter(_ => _ !== cusAttr.hour)
  239. }
  240. item.time = Array.from(new Set([...item.time]))
  241. }
  242. return item
  243. })
  244. state.selectTime = $r
  245. state.selectVisible = true
  246. }
  247. const onsubmitSchedule = async () => {
  248. if (state.scheduleName === '' || state.scheduleName === undefined) {
  249. message.warn('请填写计划名称')
  250. return
  251. }
  252. const summary = state.selectTime.map((item, index) => item.desc.length ? `星期${calcWeek(String(index + 1))} ${item.desc}` : '').filter(_ => _)
  253. const $par = {
  254. operation: 1,
  255. planName: state.scheduleName,
  256. planTime: JSON.stringify(summary),
  257. planValue: state.selectTime.map((item, index) => item.value).join('')
  258. }
  259. await AiboxCloudController.addPlan($par)
  260. state.scheduleName = ''
  261. state.selectTime = JSON.parse(JSON.stringify(initSelectTime))
  262. state.visible = false
  263. tableProDom.value.reload()
  264. }
  265. const openModal = () => {
  266. state.selectTime = JSON.parse(JSON.stringify(initSelectTime))
  267. state.visible = true
  268. }
  269. onUnmounted(() => {
  270. document.removeEventListener('mouseup', () => {})
  271. })
  272. onMounted(async () => {
  273. document.addEventListener('mouseup', () => state.selectVisible = false)
  274. })
  275. </script>
  276. <style lang='less' scoped >
  277. </style>