index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <template>
  2. <div class="oa-sys-list-view">
  3. <div class="searchBox">
  4. <div class="form">
  5. <span class="formSpan">项目名称:</span>
  6. <el-input v-model="queryParams.xmmc" placeholder="请输入项目名称" style="width: 210px" />
  7. </div>
  8. <div class="form">
  9. <span class="formSpan">项目部门:</span>
  10. <DeptTree v-model="queryParams['xmbmId']" placeholder="请选择部门" />
  11. </div>
  12. <div class="form">
  13. <span class="formSpan">跟踪人员:</span>
  14. <UserOrgTree v-model="queryParams['gzryId']" placeholder="请选择跟踪人员" />
  15. </div>
  16. <div class="from">
  17. <div class="btnBox">
  18. <el-button type="primary" style="background: #3485ff" @click="searchHandle">
  19. <img src="@/assets/imgs/OA/search.png" class="mr-8px" alt="" />
  20. 查询</el-button
  21. >
  22. <el-button type="primary" @click="addOrEditHandle()">
  23. <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
  24. 新增</el-button
  25. >
  26. </div>
  27. </div>
  28. </div>
  29. <div class="infoBox">
  30. <ul>
  31. <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
  32. <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
  33. <p>{{ item.name }}:</p>
  34. <h4 class="font-size-18px" v-money:unit="item.num"></h4>
  35. </li>
  36. </ul>
  37. </div>
  38. <div class="tableBox">
  39. <div class="table" ref="tableRef">
  40. <el-table
  41. stripe
  42. :data="tableData"
  43. style="width: 100%; height: 100%"
  44. :style="{ height: tableHeight + 'px' }"
  45. :header-cell-style="{
  46. background: '#E5F0FB',
  47. color: '#233755',
  48. height: '50px'
  49. }"
  50. >
  51. <el-table-column label="序号" width="80">
  52. <template #default="scope">{{ scope.$index + 1 }}</template>
  53. </el-table-column>
  54. <el-table-column
  55. :show-overflow-tooltip="true"
  56. prop="xmmc"
  57. label="项目名称"
  58. :min-width="220"
  59. />
  60. <el-table-column prop="gzry" label="跟踪人员" width="140" />
  61. <el-table-column
  62. prop="ygje"
  63. label="预估金额(万元)"
  64. :show-overflow-tooltip="true"
  65. width="200"
  66. />
  67. <el-table-column prop="jf" label="甲方" width="120" />
  68. <el-table-column prop="jfdjr" label="甲方对接人" width="120" />
  69. <el-table-column prop="xmbm" label="项目归属部门" width="120" />
  70. <el-table-column prop="xzqmc" label="行政区" width="120" />
  71. <el-table-column prop="zt" label="状态" width="120">
  72. <template #default="scope">
  73. {{ ztMap[scope.row.zt] }}
  74. </template>
  75. </el-table-column>
  76. <el-table-column prop="latestModifyTime" label="更新时间" width="120">
  77. <template #default="scope">
  78. {{ formatDate(scope.row.latestModifyTime) }}
  79. </template>
  80. </el-table-column>
  81. <el-table-column prop="xmjl" label="开关" width="120">
  82. <template #default="scope">
  83. <el-switch
  84. v-model="scope.row.status"
  85. :active-value="0"
  86. @change="switchChange(scope.row)"
  87. :inactive-value="1"
  88. />
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="操作" width="80" fixed="right">
  92. <template #default="scope">
  93. <div
  94. class="operateBtn"
  95. @click="addOrEditHandle(scope.row)"
  96. v-if="scope.row.gzryId === user.user.id"
  97. >
  98. <span>编辑</span>
  99. </div>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. </div>
  104. <div class="pageBox">
  105. <el-pagination
  106. v-model:current-page="queryParams.pageNo"
  107. :page-size="queryParams.pageSize"
  108. background
  109. layout="total, prev, pager, next, jumper"
  110. :total="total"
  111. @current-change="handleCurrentChange"
  112. />
  113. </div>
  114. </div>
  115. <el-dialog v-model="dialogVisible" :title="dialogTitle" width="660px" align-center>
  116. <el-form
  117. ref="ruleFormRef"
  118. style="width: 600px"
  119. label-width="auto"
  120. class="demo-ruleForm"
  121. status-icon
  122. >
  123. <el-form-item label="项目名称" prop="name">
  124. <el-input v-model="formData.xmmc" />
  125. </el-form-item>
  126. <el-row :gutter="20">
  127. <el-col :span="12">
  128. <el-form-item label="跟踪人员" prop="region">
  129. <UserOrgTree
  130. v-model="formData.gzryId"
  131. placeholder="请选择跟踪人员"
  132. @node-click="(item) => treeNodeClick(item, 'gzry')"
  133. />
  134. </el-form-item>
  135. </el-col>
  136. <el-col :span="12">
  137. <el-form-item label="甲方" prop="name">
  138. <el-input v-model="formData.jf" />
  139. </el-form-item>
  140. </el-col>
  141. </el-row>
  142. <el-row :gutter="20">
  143. <el-col :span="12">
  144. <el-form-item label="预估金额(万元)" prop="name">
  145. <el-input v-model="formData.ygje" />
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="12">
  149. <el-form-item label="甲方对接人" prop="name">
  150. <el-input v-model="formData.jfdjr" />
  151. </el-form-item>
  152. </el-col>
  153. </el-row>
  154. <el-row :gutter="20">
  155. <el-col :span="12">
  156. <el-form-item label="项目归属部门" prop="region">
  157. <DeptTree
  158. v-model="formData.xmbmId"
  159. @node-click="(item) => treeNodeClick(item, 'xmbm')"
  160. placeholder="请选择部门"
  161. />
  162. </el-form-item>
  163. </el-col>
  164. <el-col :span="12">
  165. <el-form-item label="行政区" prop="region">
  166. <DistrictTree
  167. class="form-item-disable-style"
  168. v-model="formData.xzqdm"
  169. @node-click="(item, labels) => treeNodeClick(labels, 'xzqmc')"
  170. style="width: 100%"
  171. />
  172. </el-form-item>
  173. </el-col>
  174. </el-row>
  175. <el-row :gutter="20">
  176. <el-col :span="12">
  177. <el-form-item label="状态" prop="region">
  178. <el-select v-model="formData.zt" placeholder="请选择状态" style="width: 100%">
  179. <el-option label="谋划" value="0" />
  180. <el-option label="待上会" value="1" />
  181. <el-option label="待招标" value="2" />
  182. </el-select>
  183. </el-form-item>
  184. </el-col>
  185. <el-col :span="12">
  186. <el-form-item label="谁可见" prop="region">
  187. <UserOrgTree v-model="visibleUserIds" :multiple="true" placeholder="请选择跟谁可见" />
  188. </el-form-item>
  189. </el-col>
  190. </el-row>
  191. <el-form-item label="备注" prop="desc">
  192. <el-input v-model="formData.bz" type="textarea" />
  193. </el-form-item>
  194. </el-form>
  195. <template #footer>
  196. <div class="dialog-footer">
  197. <el-button @click="dialogVisible = false">关闭</el-button>
  198. <el-button type="primary" @click="saveProjectTracking"> 保存 </el-button>
  199. </div>
  200. </template>
  201. </el-dialog>
  202. </div>
  203. </template>
  204. <script setup lang="ts">
  205. import { DICT_TYPE, getDictLabel } from '@/utils/dict'
  206. import { IFormType, useMixins, infoList, user } from './common'
  207. import request from '@/config/axios'
  208. import { formatDate } from '@/utils/formatTime'
  209. import { getAssetURL } from '@/utils/auth'
  210. import UserOrgTree from '@/views/OaSystem/components/UserOrgTree/index.vue'
  211. import DeptTree from '@/views/OaSystem/components/DeptTree/index.vue'
  212. import DistrictTree from '@/views/OaSystem/components/DistrictTree/index.vue'
  213. defineOptions({ name: 'ProjectTrack' })
  214. const ztMap = {
  215. '0': '谋划',
  216. '1': '待上会',
  217. '2': '待招标'
  218. }
  219. const visibleUserIds = ref<string[]>([])
  220. const tableRef: any = ref(null)
  221. const tableHeight: any = ref(0)
  222. const { queryParams, formData, initFormData } = useMixins()
  223. const handleCurrentChange = (pageNo: number) => {
  224. queryParams.pageNo = pageNo
  225. queryProjectTrackByPage()
  226. }
  227. /**
  228. * 项目跟踪:新增、编辑
  229. */
  230. const dialogTitle = ref<string>('项目跟踪填报')
  231. const dialogVisible = ref<boolean>(false)
  232. const addOrEditHandle = (row?: IFormType) => {
  233. dialogVisible.value = true
  234. if (!row) {
  235. dialogTitle.value = '项目跟踪填报'
  236. initFormData()
  237. visibleUserIds.value = []
  238. } else {
  239. dialogTitle.value = '项目跟踪编辑'
  240. queryProjectTrackByDetail(row['id']).then((result) => {
  241. initFormData(result as any)
  242. visibleUserIds.value = result['visibleUserIds'].split(',')
  243. })
  244. }
  245. }
  246. const treeNodeClick = (item, type: string) => {
  247. if (!item) return
  248. if (type === 'xzqmc') {
  249. formData.value[type] = item.join('-')
  250. return
  251. }
  252. formData.value[type] = item['label'] || item['name']
  253. }
  254. const saveProjectTracking = async (): Promise<void> => {
  255. const urlApi = `/projectTracking/save`
  256. const sendData = {
  257. ...formData.value
  258. }
  259. sendData['visibleUserIds'] = visibleUserIds.value.join(',')
  260. const result = await request.post({ url: urlApi, data: sendData }, '/business')
  261. if (result) {
  262. searchHandle()
  263. dialogVisible.value = false
  264. }
  265. }
  266. const switchChange = (item) => {
  267. updateStatus({
  268. id: item['id'],
  269. status: item['status']
  270. })
  271. }
  272. const updateStatus = async (data: { id: string; status: string }): Promise<void> => {
  273. const urlApi = `/update-status`
  274. return await request.put({ url: urlApi, data: data }, '/business')
  275. }
  276. const tableData = ref<Array<any>>([])
  277. const total = ref<number>()
  278. const searchHandle: () => void = () => {
  279. queryParams.pageNo = 1
  280. queryProjectTrackingSummary()
  281. queryProjectTrackByPage()
  282. }
  283. const queryProjectTrackByPage = async (): Promise<void> => {
  284. const urlApi = `/projectTracking/page`
  285. const sendData = {
  286. ...queryParams
  287. }
  288. const result = await request.get({ url: urlApi, params: sendData }, '/business')
  289. tableData.value = result['list']
  290. total.value = result['total']
  291. }
  292. const queryProjectTrackByDetail = async (id: string): Promise<void> => {
  293. const urlApi = `/projectTracking/getById`
  294. const sendData = {
  295. id
  296. }
  297. return await request.get({ url: urlApi, params: sendData }, '/business')
  298. }
  299. queryProjectTrackByPage()
  300. /**
  301. * 项目金额、项目个数汇总
  302. */
  303. const queryProjectTrackingSummary = async (): Promise<void> => {
  304. const urlApi = `/projectTracking/summary`
  305. const sendData = {
  306. ...queryParams
  307. }
  308. const result = await request.get({ url: urlApi, params: sendData }, '/business')
  309. infoList[0]['num'] = result ? result.amount ?? 0 : 0
  310. infoList[1]['num'] = result ? result.nums ?? 0 : 0
  311. }
  312. queryProjectTrackingSummary()
  313. onMounted(() => {
  314. tableHeight.value = tableRef.value.clientHeight
  315. })
  316. </script>
  317. <style lang="scss" scoped>
  318. :deep(.el-radio) {
  319. margin-right: 10px;
  320. }
  321. </style>