index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <div class="w-[100vw] bg-white page-shipping-tracking2">
  3. <div
  4. v-loading="loading"
  5. class="pt-2 w-[100%] min-h-[100vh]"
  6. >
  7. <el-form inline>
  8. <el-form-item label="Container Num">
  9. <el-input
  10. size="small"
  11. v-model="containerNumber"
  12. clearable
  13. ></el-input>
  14. </el-form-item>
  15. <el-form-item label="REF">
  16. <el-input
  17. size="small"
  18. v-model="soRef"
  19. clearable
  20. ></el-input>
  21. </el-form-item>
  22. <el-form-item>
  23. <el-tooltip
  24. content="注意 Container Number 和 REF只能同时搜一个, 如果同时输入, 那只会用REF来搜"
  25. >
  26. <el-button
  27. size="small"
  28. @click="getList()"
  29. type="primary"
  30. :loading="loading"
  31. >
  32. 搜索输入的单号/柜号
  33. </el-button>
  34. </el-tooltip>
  35. <el-button
  36. size="small"
  37. @click="getList(2)"
  38. type="warning"
  39. :loading="loading"
  40. >
  41. 搜索所有未处理申请
  42. </el-button>
  43. <el-button
  44. size="small"
  45. :loading="loading"
  46. @click="exportFunc"
  47. >
  48. 导出Excel
  49. </el-button>
  50. <el-button
  51. size="small"
  52. :loading="loading"
  53. @click="commit"
  54. >保存改动</el-button>
  55. </el-form-item>
  56. </el-form>
  57. <div
  58. class="mb-2"
  59. v-show="tabList.length"
  60. >
  61. <el-button-group>
  62. <el-button
  63. v-for="tab in tabList"
  64. :key="tab"
  65. size="small"
  66. :type="tab === currentTab ? 'primary' : ''"
  67. @click="currentTab = tab"
  68. >
  69. {{ tab.length ? tab : '未输入箱规' }}
  70. </el-button>
  71. </el-button-group>
  72. <div class="flex text-red-500 text-sm">
  73. 当前筛选得 {{ computedList.length }} 条,
  74. <!-- <br /> -->
  75. 从CRM共搜索得 {{ list.length }} 条记录
  76. </div>
  77. </div>
  78. <el-table
  79. :data="computedList"
  80. max-height="550"
  81. stripe
  82. size="small"
  83. :row-style="calcRowStyle"
  84. :row-class-name="
  85. (row: any) => {
  86. return row.editFlag ? 'table-row-edit' : ''
  87. }
  88. "
  89. border
  90. >
  91. <el-table-column
  92. fixed
  93. type="index"
  94. width="50"
  95. ></el-table-column>
  96. <el-table-column
  97. v-for="col in columnList"
  98. :key="col.prop"
  99. :width="col.width ? col.width : ''"
  100. :fixed="col.fixed ? col.fixed : false"
  101. :label="col.label"
  102. :prop="col.prop"
  103. >
  104. <template #default="scope">
  105. <div v-if="col.prop === 'Owner'">
  106. {{ getName(scope.row.Owner.id) }}
  107. </div>
  108. <div v-if="col.prop === 'Client_Label_Links'">
  109. <el-tooltip
  110. :content="scope.row.Client_Label_Links"
  111. v-if="scope.row.Client_Label_Links"
  112. >
  113. <a
  114. :href="scope.row.Client_Label_Links"
  115. target="_blank"
  116. >
  117. 点击会在新标签页打开
  118. </a>
  119. </el-tooltip>
  120. </div>
  121. <div v-if="col.prop === 'Artwork_Links'">
  122. <el-tooltip
  123. :content="scope.row.Artwork_Links"
  124. v-if="scope.row.Artwork_Links"
  125. >
  126. <a
  127. :href="scope.row.Artwork_Links"
  128. target="_blank"
  129. >
  130. 点击会在新标签页打开
  131. </a>
  132. </el-tooltip>
  133. </div>
  134. <div v-if="col.prop === 'Courier'">
  135. <el-input
  136. v-model="scope.row.Courier"
  137. @change="scope.row.editFlag = true"
  138. size="small"
  139. ></el-input>
  140. </div>
  141. <div v-if="col.prop === 'Tracking_No'">
  142. <el-input
  143. size="small"
  144. v-model="scope.row.Tracking_No"
  145. @change="scope.row.editFlag = true"
  146. ></el-input>
  147. </div>
  148. </template>
  149. </el-table-column>
  150. </el-table>
  151. </div>
  152. </div>
  153. </template>
  154. <script lang="ts" setup>
  155. import { defineComponent, ref, watch, computed, nextTick } from 'vue'
  156. import {
  157. ElNotification,
  158. ElTable,
  159. ElTableColumn,
  160. ElInput,
  161. ElForm,
  162. ElFormItem,
  163. ElButton,
  164. ElTooltip,
  165. ElTabs,
  166. ElTabPane,
  167. ElButtonGroup,
  168. ElMessage,
  169. } from 'element-plus'
  170. import cloneDeep from 'lodash.clonedeep'
  171. import dayjs from 'dayjs'
  172. import * as XLSX from 'xlsx'
  173. import request from '@/utils/axios'
  174. import { last } from 'lodash'
  175. defineComponent({
  176. name: 'ComponentShippingTracking2',
  177. })
  178. let loading = ref(false)
  179. let list = ref([] as any[])
  180. // @ts-ignore
  181. const zoho = window.ZOHO
  182. zoho.embeddedApp.on('PageLoad', function () {
  183. zoho.CRM.CONFIG.getCurrentUser().then(function (data: any) {
  184. if (Array.isArray(data.users) && data.users.length) {
  185. // const user = data.users[0]
  186. // console.log(user, 'user')
  187. // currentUser.value = user.id
  188. // currentUserName.value = user.full_name || ''
  189. // currentUserRawData.value = cloneDeep(user)
  190. // getList()
  191. getUserList()
  192. }
  193. })
  194. })
  195. let containerNumber = ref('')
  196. let soRef = ref('')
  197. let tabList = ref([] as any)
  198. let currentTab = ref('')
  199. let resetData = () => {
  200. list.value = []
  201. tabList.value = []
  202. currentTab.value = ''
  203. }
  204. let userList = ref(new Map())
  205. let getUserList = () => {
  206. return zoho.CRM.API.coql({
  207. select_query:
  208. 'select id,first_name,last_name,state from users where first_name is not null',
  209. }).then((res: any) => {
  210. console.log(res, 'res')
  211. if (Array.isArray(res.data) && res.data.length) {
  212. // userList.value = res.data
  213. res.data.forEach((i: any) => {
  214. userList.value.set(i.id, i)
  215. })
  216. }
  217. })
  218. }
  219. let getName = (id: string) => {
  220. const temp = userList.value.get(id) || {}
  221. let firstName = temp.first_name || ''
  222. let lastName = temp.last_name || ''
  223. return firstName + ' ' + lastName
  224. }
  225. const columnList = [
  226. { label: 'Urgent', prop: 'Urgent' },
  227. { label: 'REF', prop: 'SO_Reference', width: 140 },
  228. { label: 'Sales Person', prop: 'Owner', width: 120 },
  229. {
  230. label: 'Qty to be sent',
  231. prop: 'Total_Actual_Product',
  232. width: 100,
  233. },
  234. {
  235. label: 'Qty (Carton)',
  236. prop: 'Total_Quantity_Carton',
  237. width: 130,
  238. },
  239. { label: 'Weight', prop: 'Total_Weight', width: 100 },
  240. { label: 'Cube', prop: 'Total_Cube', width: 100 },
  241. {
  242. label: 'AU Standard Pallet',
  243. prop: 'AU_Standard_Pallet',
  244. width: 150,
  245. },
  246. {
  247. label: 'Delivery Notes',
  248. prop: 'Delivery_Notes',
  249. width: 200,
  250. },
  251. {
  252. label: 'Client Label Links',
  253. prop: 'Client_Label_Links',
  254. width: 145,
  255. },
  256. { label: 'Artwork Link', prop: 'Artwork_Links', width: 145 },
  257. {
  258. label: 'Time Requirement',
  259. prop: 'Time_requirement',
  260. width: 150,
  261. },
  262. { label: 'Packing', prop: 'Packing', width: 100 },
  263. {
  264. label: 'Delivery Method',
  265. prop: 'Delivery_Method',
  266. width: 160,
  267. },
  268. { label: 'Carton Mark', prop: 'Carton_Mark', width: 150 },
  269. {
  270. label: 'Container_Number',
  271. prop: 'Container_Number',
  272. width: 150,
  273. fixed: 'right',
  274. },
  275. { label: 'Courier', prop: 'Courier', width: 180, fixed: 'right' },
  276. { label: 'Tracking No', prop: 'Tracking_No', width: 180, fixed: 'right' },
  277. ]
  278. let getList = (type = 1) => {
  279. loading.value = true
  280. let sql =
  281. 'select ' +
  282. columnList.map((i: any) => `Shipping_Tracking.${i.prop}`).join(',') +
  283. ' from Shipping_Tracking '
  284. let whereSQL =
  285. " (Package_Type='SGL Package' and Confirm_send_to_Starshipit=true) "
  286. if (type === 2) {
  287. sql += ' where (Tracking_No is null or Courier is null) and' + whereSQL
  288. } else if (soRef.value) {
  289. sql = sql + ` where (SO_Reference like '%${soRef.value}%') and` + whereSQL
  290. } else if (containerNumber.value) {
  291. sql +=
  292. ` where (Container_Number like '%${containerNumber.value}%') and` +
  293. whereSQL
  294. } else {
  295. sql += ' where ' + whereSQL
  296. }
  297. return zoho.CRM.API.coql({
  298. select_query: sql,
  299. })
  300. .then((res: any) => {
  301. console.log(res, 'res')
  302. if (Array.isArray(res.data) && res.data.length) {
  303. list.value = res.data.map((i: any) => {
  304. return {
  305. ...i,
  306. editFlag: false,
  307. }
  308. })
  309. const temp = res.data
  310. .filter(
  311. (i: any) =>
  312. ![null, 'null', '', '-', '_', 'N/A'].includes(i.Container_Number),
  313. )
  314. .map((i: any) => i.Container_Number)
  315. // tabList.value 去重
  316. tabList.value = [...new Set(temp)]
  317. if (tabList.value.length) tabList.value.unshift('')
  318. console.log(tabList.value.length, 'tabList.value.length')
  319. if (tabList.value.length > 1) currentTab.value = tabList.value[1]
  320. } else if (res.status === 204) {
  321. ElNotification({
  322. type: 'warning',
  323. title: 'No Data Found',
  324. message: res.statusText || `zoho api return: ${res.status}`,
  325. duration: 3000,
  326. })
  327. resetData()
  328. } else {
  329. resetData()
  330. }
  331. })
  332. .catch(() => {
  333. resetData()
  334. })
  335. .finally(() => {
  336. loading.value = false
  337. })
  338. }
  339. let computedList = computed(() =>
  340. currentTab.value
  341. ? list.value.filter((i) => i.Container_Number === currentTab.value)
  342. : list.value.filter((i) => ['', 'null', null].includes(i.Container_Number)),
  343. )
  344. zoho.embeddedApp.init()
  345. // 给表格加红绿背景. 颜色用的tailwind的 red green
  346. const calcRowStyle = ($e: any) => {
  347. const result = {} as any
  348. if ($e.row.editFlag) result['background-color'] = 'rgb(187, 247, 208)'
  349. return result
  350. }
  351. // 帮我把导出表格的表头, 从columnList中获取的prop改为label, 但是表格其他数据不变
  352. let exportFunc = () => {
  353. if (!computedList.value.length) {
  354. ElNotification({
  355. type: 'warning',
  356. title: '换个tab筛选数据吧',
  357. message: '当前表格没有数据可以导出',
  358. duration: 3000,
  359. })
  360. return
  361. }
  362. const sheetData = computedList.value.map((i) => {
  363. let result = {
  364. ...cloneDeep(i),
  365. Urgent: `${i.Urgent}`,
  366. Owner: getName(i.Owner.id),
  367. }
  368. delete result.id
  369. delete result.editFlag
  370. // 关键:根据 columnList 顺序构建导出对象
  371. let ordered: { [label: string]: any } = {}
  372. columnList.forEach((col) => {
  373. ordered[col.label] = result[col.prop]
  374. })
  375. return ordered
  376. })
  377. const sheet1 = XLSX.utils.json_to_sheet(sheetData, {
  378. header: columnList.map((i) => i.label),
  379. })
  380. const wb = XLSX.utils.book_new()
  381. sheet1['!cols'] = columnList.map((i) => {
  382. return { wpx: i.width ? i.width + 30 : 110 }
  383. })
  384. XLSX.utils.book_append_sheet(wb, sheet1, 'sheet1')
  385. let name = currentTab.value || '未输入箱规'
  386. XLSX.writeFile(wb, name + '.xlsx')
  387. }
  388. const commit = () => {
  389. if (loading.value) return
  390. // loading.value = true
  391. ElMessage.info('正在开发中')
  392. }
  393. </script>
  394. <style lang="scss" scoped></style>